In C#, how to kill a process tree reliably
c#, process
Solution
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.
}
}
Problem
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 { } } } ```