Question: How can I determine all processes in the child's Process Tree to kill them?
I have an application, written in C# that will:
- Get a set of data from the server,
- Spawn a 3rd party utility to process the data, then
- Return the results to the server.
This is working fine. But since a run consumes a lot of CPU and may take as long as an hour, I want to add the ability to have my app terminate its child processes.
Some issues that make the simple solutions I've found elsewhere are:
- My app's child process "A" (InstallAnywhere EXE I think) spawns the real processing app "B" (a java.exe), which in turns spawns more children "C1".."Cn" (most of which are also written in Java).
- There will likely be multiple copies of my application (and hence, multiple sets of its children) running on the same machine.
- The child process is not in my control so there might be some "D" processes in the future.
- My application must run on 32-bit and 64-bit versions of MSWindows.
On the plus side there is no issue of data loss, a "clean" shutdown doesn't matter as long as the processes end fairly quickly.
I guess you can kill your grandchildren with this code from the MSDN forums.
public bool killProcess(int pid)
{
bool didIkillAnybody = false;
try
{
Process[] procs = Process.GetProcesses();
for (int i = 0; i < procs.Length; i++)
{
didIkillAnybody = GetParentProcess(procsIdea.Id) == pid) &&
killProcess(procsIdea.Id);
}
try
{
Process myProc = Process.GetProcessById(pid);
myProc.Kill();
return true;
}
catch { }
}
catch (Exception ex)
{
try
{
new Logger().Write("Exception caught at JobExecution.killProcess()", ex.Message, System.Diagnostics.EventLogEntryType.Warning, false);
}
catch { }
}
return didIkillAnybody;
}
private int GetParentProcess(int Id)
{
int parentPid = 0;
using (ManagementObject mo = new ManagementObject("win32_process.handle='" + Id.ToString() + "'"))
{
mo.Get();
parentPid = Convert.ToInt32(mo["ParentProcessId"]);
}
return parentPid;
}
Based on the solution outlined on this site, here is a compact way of doing it:
static public void KillChildren(int parentPid)
{
foreach (var pid in
from ManagementBaseObject m in new ManagementObjectSearcher("select ProcessId from Win32_Process where ParentProcessId=" + parentPid).Get()
select Convert.ToInt32(m["ProcessId"]))
KillChildren(pid);
Process.GetProcessById(parentPid).Kill();
}
The following code works for me:
private void KillProcessAndChildren(int pid)
{
using (var searcher = new ManagementObjectSearcher("Select * From Win32_Process Where ParentProcessID=" + pid))
using (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 */ }
}
}
It works for the scenario I have. I'd be interested to hear if that works for others as well.
I tested Jake Pearson's solution and for me this does not always work. I wanted to kill other process (with known pid) tree. The other process was using iexplore.exe running separately for each instance (IE 8 - more than one process). It works fine, but when used with WinAPI to hide IE window it stopped working.
I found solution on microsoft.public.dotnet.framework group, and it works fine now. Although Jake's answer can be useful in most cases, I think.