以前有人问过这个问题,但我在代码中找不到明确的答案。
我打开一个进程 ProcessA(PID 为 1234)。此进程打开一个子进程 ProcessAB (PID 5678)。完成后,我终止了 ProcessA,但我仍然有 ProcessAB 的挥之不去。
如何终止整个进程树?我的意思是,我如何确保如果我终止我打开的进程,我也会终止所有关联的进程?
谢谢
代码表示赞赏。
检查此线程以在“作业”中对进程进行分组。
如果这对您不起作用,则采用本土方法可能如下:
示例代码:
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);
}
}
使用作业对象。
这是最接近 windows 必须提供的 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;
}
有How To Kill a Process Tree,但它在 C# 中。我认为将其移植到 C 并不难。
@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);
}
}
纯 C 非常快速和肮脏的方法:使用system()
withtaskkill.exe
/* Kill process tree in C on windows: quick and very dirty solution */
void killtree(DWORD pid, char force, char tree) {
char cmd[1024];
char *forceflag = force ? " /F" : "";
char *treeflag = tree ? " /T" : "";
sprintf(cmd, "taskkill%s%s /PID %lu", forceflag, treeflag, pid);
system(cmd);
/* optional additional code-- see below */
if(process_is_running(pid)) {
fprintf(errlog, "couldn't kill %lu\r\n", pid);
fflush(errlog);
}
}
/* if you want, you might also want to use process_is_running() */
static char process_is_running(DWORD pid) {
if(!pid)
return 0;
HANDLE process = OpenProcess(SYNCHRONIZE, FALSE, pid);
DWORD ret = WaitForSingleObject(process, 0);
CloseHandle(process);
return ret == WAIT_TIMEOUT;
}
以下内容适用于 Linux,但我希望它对 Windows 有所帮助。
当你 fork() 时,保存返回值,即子进程的 pid,然后当父进程即将退出时,kill() pid。
如果您有多个子进程,则可以将 kill 发送到进程组。默认情况下,子进程具有与父进程相同的 pgid。