终止进程树(C for Windows)

这已经被问过,但我无法find一个明确的答案,在代码中。

我打开一个进程ProcessA(带有PID 1234)。 这个过程打开一个subprocessProcessAB(PID 5678)。 完成之后,我终止了ProcessA,但我仍然有ProcessAB的挥之不去。

我如何终止整个过程树? 我的意思是,我如何确定如果我终止了我打开的进程,我也终止了所有相关的进程?

谢谢

代码表示赞赏。

检查此线程是否在“作业”中分组进程。

如果这不适合你,一个家庭成长的方法可能如下:

  1. 获取您的主进程ID
  2. 调用CreateToolhelp32Snapshot来枚举系统上的所有进程
  3. 检查每个进程的PROCESSENTRY32结构的th32ParentProcessID成员,如果它匹配您的父ID,则终止进程(使用TerminateProcess
  4. 所有孩子终止后,终止主流程

示例代码:

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

使用作业对象 。

这是窗口所能提供的最接近unix“流程组”的东西。

作业对象允许您指示一个子进程(及其所有子进程)可以一起管理, 被杀害 与unix不同,在撰写本文时,“作业对象” 不能嵌套 这意味着,如果一个父母创建一个孩子的工作对象,所有孩子的孩子不能自己使用工作对象(这是一个/严重/限制恕我直言,就像一个文件系统,只允许一级子目录)。

用ALL杀死一棵树! 孩子的:

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

有如何杀死进程树 ,但它是在C#中。 我不认为把它移到C是不是太难

请参阅NtQueryInformationProcess函数和TerminateProcess函数 。

@mjmarsh答案需要递归的自制案件,否则这是正确的。 创建工作对象比你更好的时候可以。

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

以下是针对Linux,但我希望它有一些适应Windows帮助。

当你fork()时,保存返回值,这是子进程的pid,那么当父进程将要退出时,kill()这个pid。

如果您有多个子进程,则可以将kill消息发送到进程组。 默认情况下,子进程与父进程具有相同的pgid。