12

以前有人问过这个问题,但我在代码中找不到明确的答案。

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

如何终止整个进程树?我的意思是,我如何确保如果我终止我打开的进程,我也会终止所有关联的进程?

谢谢

代码表示赞赏。

4

7 回答 7

11

检查此线程以在“作业”中对进程进行分组。

如果这对您不起作用,则采用本土方法可能如下:

  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);
    }       
}
于 2009-07-23T17:49:53.287 回答
5

使用作业对象

这是最接近 windows 必须提供的 unix“进程组”的东西。

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

于 2011-05-26T12:06:40.123 回答
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;
}
于 2010-01-28T10:42:23.293 回答
0

How To Kill a Process Tree,但它在 C# 中。我认为将其移植到 C 并不难。

请参阅NtQueryInformationProcess 函数TerminateProcess 函数

于 2009-07-23T17:46:06.697 回答
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);
    }
}
于 2016-03-18T16:45:24.523 回答
0

纯 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;
}
于 2020-04-09T02:50:10.840 回答
-1

以下内容适用于 Linux,但我希望它对 Windows 有所帮助。

当你 fork() 时,保存返回值,即子进程的 pid,然后当父进程即将退出时,kill() pid。

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

于 2009-07-23T17:42:39.450 回答