Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In C#, how to kill a process tree reliably [duplicate]

Tags:

c#

process

In C#, we use the following code to kill a process tree. Sometimes it works, and sometimes it doesn't, possibly having to do with Windows 7 and/or 64-bit.

The way it finds children of the given process is by calling GetProcesses to get all the processes in the system, and then calling NtQueryInformationProcess to find out every process whose parent is the given process. It does this recursively, to walk the tree.

The on-line doc says NtQueryInformationProcess should not be used. Instead there is something called EnumProcesses, but I can't find any examples in C#, only other languages.

What's a reliable way to kill a tree of processes in 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 { }
        }
    }
like image 320
Mike Dunlavey Avatar asked Mar 19 '23 12:03

Mike Dunlavey


1 Answers

Use ManagmentObjectSearcher and a little recursion:

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.
    }
 }
like image 194
Yuval Itzchakov Avatar answered Apr 12 '23 23:04

Yuval Itzchakov