Terminar un árbol de proceso (C para Windows)

Esto se ha preguntado antes, pero no puedo encontrar una respuesta definitiva, en el código.

Abro un proceso, ProcessA (con PID 1234). Este proceso abre un proceso hijo, ProcessAB (PID 5678). Después de terminar, termino el proceso A pero todavía me queda el tiempo de ProcessAB.

¿Cómo termino el árbol de proceso completo? Lo que quiero decir es, ¿cómo me aseguro de que si finalizo el proceso que abrí, también estoy finalizando todos los procesos asociados?

Gracias

Código es apreciado.

Verifique este hilo para los procesos de agrupamiento dentro de un “trabajo”.

Si eso no funciona para usted, un enfoque de cosecha propia podría ser el siguiente:

  1. Obtenga su ID de proceso principal
  2. Llame a CreateToolhelp32Snapshot para enumerar todos los procesos en el sistema
  3. Compruebe el miembro th32ParentProcessID de la estructura PROCESSENTRY32 en cada proceso, si coincide con su ID principal, luego termine el proceso (usando TerminateProcess )
  4. Después de terminar a todos los niños, finalice el proceso principal

Código de muestra:

DWORD myprocID = 1234; // your main process id PROCESSENTRY32 pe; memset(&pe, 0, sizeof(PROCESSENTRY32)); pe.dwSize = sizeof(PROCESSENTRY32); HANDLE hSnap = :: CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (::Process32First(hSnap, &pe)) { BOOL bContinue = TRUE; // kill child processes while (bContinue) { // only kill child processes if (pe.th32ParentProcessID == myprocID) { HANDLE hChildProc = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, pe.th32ProcessID); if (hChildProc) { ::TerminateProcess(hChildProc, 1); ::CloseHandle(hChildProc); } } bContinue = ::Process32Next(hSnap, &pe); } // kill the main process HANDLE hProc = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, myprocID); if (hProc) { ::TerminateProcess(hProc, 1); ::CloseHandle(hProc); } } 

Usa objetos de trabajo .

Es lo más parecido a un ‘grupo de procesos’ de UNIX que Windows tiene para ofrecer.

Los objetos de trabajo le permiten indicar que un proceso hijo (y todos sus elementos secundarios) se pueden gestionar juntos, esp. por ser asesinado A diferencia de Unix, a partir de este escrito no se pueden anidar ‘objetos de trabajo’. Lo que significa que si un padre crea un objeto de trabajo para un niño, todos los hijos de ese niño no pueden usar Objetos de trabajo (que es un / grave / limitación en mi humilde opinión, como un sistema de archivos que solo permite un nivel de subdirectorios).

Para matar un árbol entero con TODO! niños:

 bool __fastcall KillProcessTree(DWORD myprocID, DWORD dwTimeout) { bool bRet = true; HANDLE hWnd; PROCESSENTRY32 pe; memset(&pe, 0, sizeof(PROCESSENTRY32)); pe.dwSize = sizeof(PROCESSENTRY32); HANDLE hSnap = :: CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (::Process32First(hSnap, &pe)) { BOOL bContinue = TRUE; // kill child processes while (bContinue) { if (pe.th32ParentProcessID == myprocID) { ShowMessage ("Gleich - KILL PID: " + AnsiString(pe.th32ProcessID)); // Rekursion KillProcessTree(pe.th32ProcessID, dwTimeout); HANDLE hChildProc = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, pe.th32ProcessID); if (hChildProc) { GetWindowThreadProcessId(hWnd, &myprocID); // CLOSE Message s PostMessage(hWnd, WM_CLOSE, 0, 0) ; if (WaitForSingleObject(hChildProc, dwTimeout) == WAIT_OBJECT_0) bRet = true; else { bRet = TerminateProcess(hChildProc, 0); } ::CloseHandle(hChildProc); } } bContinue = ::Process32Next(hSnap, &pe); } // kill the main process HANDLE hProc = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, myprocID); if (hProc) { ::TerminateProcess(hProc, 1); ::CloseHandle(hProc); } } return bRet; } 

Hay cómo matar un árbol de proceso , pero está en C #. No creo que sea demasiado difícil portar eso a C.

Ver NtQueryInformationProcess Function y TerminateProcess Function .

@mjmarsh responde necesita recurrencia para el caso homebrew, de lo contrario es el correcto. Crear objetos de trabajo es mejor que el siguiente cuando pueda.

 void KillProcessTree(DWORD myprocID) { PROCESSENTRY32 pe; memset(&pe, 0, sizeof(PROCESSENTRY32)); pe.dwSize = sizeof(PROCESSENTRY32); HANDLE hSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (::Process32First(hSnap, &pe)) { do // Recursion { if (pe.th32ParentProcessID == myprocID) KillProcessTree(pe.th32ProcessID); } while (::Process32Next(hSnap, &pe)); } // kill the main process HANDLE hProc = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, myprocID); if (hProc) { ::TerminateProcess(hProc, 1); ::CloseHandle(hProc); } } 

Lo siguiente es para Linux, pero espero que ayude a Windows con alguna adaptación.

Cuando fork (), guarda el valor de retorno, que es el pid del proceso hijo, cuando el padre está a punto de salir, kill () el pid.

Si tiene múltiples procesos secundarios, puede enviar el kill al grupo de procesos. De forma predeterminada, los procesos secundarios tienen el mismo pgid que el primario.