以前曾经问过,但我在代码中找不到明确的答案。
我打开一个进程,ProcessA(带有PID 1234)。此过程打开子进程ProcessAB(PID 5678)。 在我完成后,我终止了ProcessA,但我仍然留有ProcessAB。
如何终止整个流程树?我的意思是,我如何确保如果我终止我打开的流程,我也会终止所有相关流程?
由于
感谢代码。
答案 0 :(得分:12)
检查this thread是否在“工作”中分组流程。
如果这对您不起作用,本土方法可能如下:
示例代码:
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);
}
}
答案 1 :(得分:5)
使用Job Objects。
它与Windows提供的unix'进程组'最接近。
作业对象允许您指示子进程(及其所有子进程)可以一起管理,尤其是。因为被杀与unix不同,在撰写本文时,“作业对象”不能嵌套。这意味着如果父母为孩子创建了一个工作对象,那么孩子的所有孩子都不能自己使用工作对象(这是一个/严重/限制恕我直言,就像只允许一级子目录的文件系统一样。)
答案 2 :(得分:3)
用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;
}
答案 3 :(得分:0)
有How To Kill a Process Tree,但它在C#中。我不认为把它移植到C上太难了。
请参阅NtQueryInformationProcess Function和TerminateProcess Function。
答案 4 :(得分:0)
@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);
}
}
答案 5 :(得分:0)
纯C的方法非常肮脏:将system()
与taskkill.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;
}
答案 6 :(得分:-1)
以下内容适用于Linux,但我希望它可以帮助Windows进行一些改编。
当你fork()时,保存返回值,这是子进程的pid,然后当父进程退出时,kill()pid。
如果您有多个子进程,则可以将kill发送到进程组。默认情况下,子进程与父进程具有相同的pgid。