Terminer une arborescence de processus (C pour Windows)

Cela a été demandé auparavant, mais je ne peux pas trouver une réponse définitive, en code.

J’ouvre un processus, ProcessA (avec PID 1234). Ce processus ouvre un processus enfant, ProcessAB (PID 5678). Après avoir terminé, je termine ProcessA, mais j’ai toujours la fin de ProcessAB.

Comment puis-je terminer l’arborescence de processus? Qu’est-ce que je veux dire, comment puis-je m’assurer que si je termine le processus que j’ai ouvert, je termine également tous les processus associés?

Merci

Le code est apprécié.

Vérifiez ce thread pour regrouper les processus dans un “job”.

Si cela ne fonctionne pas pour vous, une approche locale pourrait être la suivante:

  1. Obtenez votre identifiant de processus principal
  2. Appelez CreateToolhelp32Snapshot pour énumérer les processus sur le système
  3. Vérifiez le membre th32ParentProcessID de la structure PROCESSENTRY32 sur chaque processus, s’il correspond à votre ID parent, puis terminez le processus (à l’aide de TerminateProcess )
  4. Une fois tous les enfants terminés, mettez fin au processus principal

Exemple de code:

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); } } 

Utilisez des objects de travail .

C’est la chose la plus proche d’un groupe de processus Unix que Windows a à offrir.

Les objects de travail vous permettent d’indiquer qu’un processus enfant (et tous ses enfants) peuvent être gérés ensemble, en particulier. pour avoir été tué. Contrairement à unix, à ce jour, les «objects de travail» ne peuvent pas être nesteds . Ce qui signifie que si un parent crée un object métier pour un enfant, tous les enfants de cet enfant ne peuvent eux-mêmes utiliser des objects de travail (qui est un IMHO grave / limitatif, comme un système de fichiers ne permettant qu’un niveau de sous-répertoires).

Tuer un arbre entier avec TOUS !!! enfants:

 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: " + AnsiSsortingng(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; } 

Comment tuer un arbre de processus , mais il est en C #. Je ne pense pas qu’il soit trop difficile de porter cela à C.

Voir Fonction NtQueryInformationProcess et Fonction TerminateProcess .

@mjmarsh répond a besoin d’une récursivité pour le cas de l’homebrew, sinon c’est le bon. Il est préférable de créer des objects de travail lorsque vous le pouvez.

 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); } } 

Ce qui suit est pour Linux, mais j’espère que cela aidera Windows avec quelques adaptations.

Lorsque vous utilisez fork (), enregistrez la valeur de retour, qui est le pid du processus enfant, puis, lorsque le parent est sur le sharepoint quitter, tuez () le pid.

Si vous avez plusieurs processus enfants, vous pouvez envoyer le kill au groupe de processus. Par défaut, les processus enfants ont le même identifiant que le parent.