2014-05-24 64 views
4

在C#中,我们使用以下代码来终止进程树。 有时它有效,有时它不会,可能与Windows 7和/或64位有关。在C#中,如何可靠地终止进程树

找到给定进程的子进程的方式是调用GetProcesses以获取系统中的所有进程,然后调用NtQueryInformationProcess来查找其父进程是给定进程的每个进程。 它递归地执行此操作,以走树。

在线文档说不应使用NtQueryInformationProcess。 取而代之的是EnumProcesses,但我在C#中找不到任何示例,只有其他语言。

什么是杀死C#中进程树的可靠方法?

public static void TerminateProcessTree(Process process) 
    { 
     IntPtr processHandle = process.Handle; 
     uint processId = (uint)process.Id; 

     // Retrieve all processes on the system 
     Process[] processes = Process.GetProcesses(); 
     foreach (Process proc in processes) 
     { 
      // Get some basic information about the process 
      PROCESS_BASIC_INFORMATION procInfo = new PROCESS_BASIC_INFORMATION(); 
      try 
      { 
       uint bytesWritten; 
       Win32Api.NtQueryInformationProcess(proc.Handle, 0, ref procInfo, 
        (uint)Marshal.SizeOf(procInfo), out bytesWritten); // == 0 is OK 

       // Is it a child process of the process we're trying to terminate? 
       if (procInfo.InheritedFromUniqueProcessId == processId) 
       { 
        // Terminate the child process (and its child processes) 
        // by calling this method recursively 
        TerminateProcessTree(proc); 
       } 
      } 
      catch (Exception /* ex */) 
      { 
       // Ignore, most likely 'Access Denied' 
      } 
     } 

     // Finally, terminate the process itself: 
     if (!process.HasExited) 
     { 
      try 
      { 
       process.Kill(); 
      } 
      catch { } 
     } 
    } 
+1

(http://stackoverflow.com/q/604522)在C++中的窗口上执行的 “杀死进程树” 等效(清楚你已经知道如何P/Invoke) –

+0

您的问题简化为“如何查找所有子进程”。杀死它们是问题的微不足道的延伸。因此这是重复的。 – usr

+0

@usr:感谢您举报该问题。我仍然试图找出使用'using'语句的用法。 –

回答

7

使用ManagmentObjectSearcher和少许递归:

private static void KillProcessAndChildren(int pid) 
{ 
    ManagementObjectSearcher searcher = new ManagementObjectSearcher 
     ("Select * From Win32_Process Where ParentProcessID=" + pid); 
    ManagementObjectCollection moc = searcher.Get(); 
    foreach (ManagementObject mo in moc) 
    { 
     KillProcessAndChildren(Convert.ToInt32(mo["ProcessID"])); 
    } 
    try 
    { 
     Process proc = Process.GetProcessById(pid); 
     proc.Kill(); 
    } 
    catch (ArgumentException) 
    { 
     // Process already exited. 
    } 
} 
+0

原谅我的天真',但我试过'使用System.Management;',似乎并没有给我访问它。我肯定错过了什么。 –

+1

您是否添加了对“System.Management.dll”的引用? –

+1

这样做。感谢您帮助我解决问题。 –