在C#中,如何可靠地杀死进程树

时间:2014-05-24 13:06:20

标签: c# process

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

它找到给定进程的子进程的方法是调用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 个答案:

答案 0 :(得分: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.
    }
 }