Answered by:
How to find the child processes associated with a PID?

Question
-
Hello everyone,
I'm launching a cmd line script from a c# application with:
cmd /c randomscript.cmd
I save the PID so i can later kill it but, since the "randomscript.cmd" launches other applications, the application doesn't actually stop when i kill it (because the other applications launched by my randomscript.cmd).
Basically, i've found that i should look for all the childs associated with a given PID so i can then kill them.
Does anybody know how i can do this?
I have an example for getting the parent id for a given child but that's exactly the opposite from what i want to achieve: i want the CHILD for the given Parent!
Thanks in advance!
Luís Silva
Answers
-
For whoever might care, the solution is here:
/*
* kill a job by its PID
* and all associated childs
*/
public bool killProcess(int pid)
{
bool didIkillAnybody = false;
try
{
Process[] procs = Process.GetProcesses();
for (int i = 0; i < procs.Length; i++)
{
if (GetParentProcess(procs.Id) == pid)
/*
* the good thing about this
* is that we will also kill
* any child for the child process! ;o)
* will this be a memory hog?
*/
if (killProcess(procs.Id) == true)
didIkillAnybody = true;
}
try
{
/*
* basically, the fact that we killed all the child
* could have DEVASTED the parent which, sadly,
* could have commited suicide!
*/
Process myProc = Process.GetProcessById(pid);
myProc.Kill();
return true;
}
catch { }
}
catch (Exception ex)
{
try
{
Logger log = new Logger();
log.Write("Exception caught at JobExecution.killProcess()", ex.Message, System.Diagnostics.EventLogEntryType.Warning, false);
}
catch { }
}
return didIkillAnybody;
}
/*
* get parent process for a given PID
*/
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;
}
This other thread i posted really helped me:
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2946225&SiteID=1&mode=1
All replies
-
Basically, i'm looking for something that does the exact same as:
C:\Documents and Settings\Administrator>taskkill /PID 4316 /T /F
SUCCESS: The process with PID 2124 (child process of PID 4316) has been terminated.
SUCCESS: The process with PID 4316 (child process of PID 792) has been terminated.
C:\Documents and Settings\Administrator>
Thanks! -
For whoever might care, the solution is here:
/*
* kill a job by its PID
* and all associated childs
*/
public bool killProcess(int pid)
{
bool didIkillAnybody = false;
try
{
Process[] procs = Process.GetProcesses();
for (int i = 0; i < procs.Length; i++)
{
if (GetParentProcess(procs.Id) == pid)
/*
* the good thing about this
* is that we will also kill
* any child for the child process! ;o)
* will this be a memory hog?
*/
if (killProcess(procs.Id) == true)
didIkillAnybody = true;
}
try
{
/*
* basically, the fact that we killed all the child
* could have DEVASTED the parent which, sadly,
* could have commited suicide!
*/
Process myProc = Process.GetProcessById(pid);
myProc.Kill();
return true;
}
catch { }
}
catch (Exception ex)
{
try
{
Logger log = new Logger();
log.Write("Exception caught at JobExecution.killProcess()", ex.Message, System.Diagnostics.EventLogEntryType.Warning, false);
}
catch { }
}
return didIkillAnybody;
}
/*
* get parent process for a given PID
*/
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;
}
This other thread i posted really helped me:
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2946225&SiteID=1&mode=1 -
This may be a very late post, but I had a question regarding the usage of ManagementObject.
Firstly, Thanks a lot for posting your solution. This has been very useful for me as I had a very similar situation where I launch a script and the script launches other processes that I need to kill. The solution above seems to work fine most of the time. At some instances though, mo.Get() results in the exception below:
Message:Not found
Stacktrace: at System.Management.ManagementException.ThrowWithExtendedInfo(ManagementStatus errorCode)
at System.Management.ManagementObject.Get()
I have looked around but have not found any reason why this happens. After this exception is thrown, the child process gets orphaned and I end up killing it manually.
Have you faced this issue? Any input would be very useful.
Thanks
-
I found this code to work for me:
private 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 */ } }
- Proposed as answer by Fuzzy.Logician Friday, March 9, 2012 8:40 PM
-
-
public void StopProcess(Process p)
{
if (p != null)
{
Process KillerP = new Process();
KillerP.StartInfo.FileName = "taskkill.exe";
KillerP.StartInfo.Arguments = "/PID " + p.Id + " /T /F";
KillerP.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
KillerP.Start();
KillerP.WaitForExit();
}
}- Proposed as answer by Magnum_2007 Thursday, August 30, 2012 12:28 PM
-
Don't get put off by the name of the routine Familicide: a slight modification of RonaldDev's KillProcessAndChildren.
Regards, Paul
private void Familicide(int pid)
{
// kill a process tree (family)
// this code requires the reference for System.Managemnt.dll
// First a list of children is build in pids. Then the process with pid is killed and Familicide is called for each child.
// If a straight recursive approach is used, than it's possible to miss-out on children created between the call to
// Familicide and requesting the list of children through the searcher.
SortedSet<Int32> pids = new SortedSet<Int32>();
System.Management.ManagementObjectSearcher searcher = new System.Management.ManagementObjectSearcher("Select * From Win32_Process Where ParentProcessID=" + pid);
System.Management.ManagementObjectCollection moc = searcher.Get;
foreach (System.Management.ManagementObject mo in moc) {
try {
pids.Add(Convert.ToInt32(mo.Item("ProcessID")));
} catch {
// process already exited, so get Item("ProcessID") will raise an error
}
}
try {
Process aProcess = Process.GetProcessById(pid);
aProcess.Kill();
} catch (ArgumentException ex) {
// process already exited
}
foreach (Int32 aChildPid in pids) {
Familicide(aChildPid);
}
}PE