none
How to find the child processes associated with a PID? RRS feed

  • 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
    Monday, March 3, 2008 1:11 PM

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(procsIdea.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(procsIdea.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
    Tuesday, March 4, 2008 12:28 PM

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!
    Monday, March 3, 2008 1:22 PM
  • 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(procsIdea.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(procsIdea.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
    Tuesday, March 4, 2008 12:28 PM
  • 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

    Wednesday, March 17, 2010 6:21 PM
  • 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 */ }
    }
    
    Thursday, March 3, 2011 7:16 PM
  • Excelent method! @RonaldDev
    Wednesday, August 24, 2011 8:49 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
    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

    Tuesday, April 30, 2013 1:24 AM