2011-08-25 4 views
6

Ho una libreria di classi .NET che gira su un processo secondario che viene mantenuto in esecuzione fino a quando non dispongo dell'oggetto.Trova tutti i processi figli del mio processo .NET/scopri se un dato processo è un mio figlio?

A causa di alcune occorrenze del programma che persistono in memoria, ho deciso di aggiungere un test di integrazione per garantire che se lascio che l'oggetto si imposti su GC/Finalization, tale processo viene centrifugato.

Tuttavia, poiché il processo è il client della riga di comando di Mercurial e il mio build server sta già eseguendo Mercurial come parte delle proprie operazioni, immagino le situazioni in cui Mercurial è già in esecuzione all'avvio del test o che è stato avviato , ed è ancora in esecuzione, al termine del test, in relazione al build server, e non al mio test.

Quindi, voglio assicurarmi che il client Mercurial che trovo (o meno) sia quello che ho avviato, e non solo qualsiasi client attualmente in esecuzione.

Quindi la domanda è questa:

  • Come posso sapere se il cliente Mercurial sto guardando è stato avviato da mio processo?

Per "guardare", stavo cercando di utilizzare il metodo Process.GetProcesses, ma questo non è un requisito.

Se una domanda diversa è meglio, "Come trovare tutti i processi figlio del mio processo", vale a dire. più facile rispondere, anche quello è più che sufficiente.

Ho trovato questa pagina: How I can know the parent process ID of a process?, ma sembra che devo dargli il nome del processo. Se mi limito a dargli "hg", questa domanda non è ambigua per il caso che sto cercando?

risposta

16

come accade, ho un po 'di codice C#/WMI in giro che uccide tutti i processi generati da un ID processo specificato, in modo ricorsivo. l'uccisione non è ovviamente ciò che si vuole, ma il ritrovamento di processi figli sembra essere quello che vi interessa Spero che questo è utile:.

private static void KillAllProcessesSpawnedBy(UInt32 parentProcessId) 
    { 
     logger.Debug("Finding processes spawned by process with Id [" + parentProcessId + "]"); 

     // NOTE: Process Ids are reused! 
     ManagementObjectSearcher searcher = new ManagementObjectSearcher(
      "SELECT * " + 
      "FROM Win32_Process " + 
      "WHERE ParentProcessId=" + parentProcessId); 
     ManagementObjectCollection collection = searcher.Get(); 
     if (collection.Count > 0) 
     { 
      logger.Debug("Killing [" + collection.Count + "] processes spawned by process with Id [" + parentProcessId + "]"); 
      foreach (var item in collection) 
      { 
       UInt32 childProcessId = (UInt32)item["ProcessId"]; 
       if ((int)childProcessId != Process.GetCurrentProcess().Id) 
       { 
        KillAllProcessesSpawnedBy(childProcessId); 

        Process childProcess = Process.GetProcessById((int)childProcessId); 
        logger.Debug("Killing child process [" + childProcess.ProcessName + "] with Id [" + childProcessId + "]"); 
        childProcess.Kill(); 
       } 
      } 
     } 
    } 
+1

Questo ha funzionato magnificamente per me, anche se ho optato per un approccio più semplice usando ManagementObject e nessun ricercatore. Avevo lottato per uccidere i miei sottoprocessi per un po ', grazie! – Darkhydro

+0

Life saver !!!!!! – mstrewe

0

Benche la answer of mtijn è probabilmente il più vicino si può ger, la la vera risposta è: non puoi.

Windows non mantiene un albero del processo reale in cui i processi vengono ristrutturati quando un processo su un livello intermedio muore. Tuttavia, Windows ricorda l'ID del processo principale.

Il caso problematico è il seguente:

originale struttura di processo:

YourApp.exe 
- SubApp.exe 
    - Second.exe 

Se ora SubApp.exe termina, non verrà aggiornato l'ID del processo padre di Second.exe. Il nuovo risultato è

YourApp.exe 
Second.exe 

È possibile verificare utilizzando SysInternals Process Explorer. È in grado di mostrare i processi come un albero. Avviare CMD, quindi digitare start cmd. Nella nuova finestra, digita di nuovo start cmd. Avrai 3 finestre aperte. Ora termina quello centrale.