终止进程树(C for Windows)

时间:2009-07-23 17:39:26

标签: c windows process terminate

以前曾经问过,但我在代码中找不到明确的答案。

我打开一个进程,ProcessA(带有PID 1234)。此过程打开子进程ProcessAB(PID 5678)。 在我完成后,我终止了ProcessA,但我仍然留有ProcessAB。

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

由于

感谢代码。

7 个答案:

答案 0 :(得分:12)

检查this thread是否在“工作”中分组流程。

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

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

        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 FunctionTerminateProcess 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。