Retrieving the Parent Process of a Child when Multiple Instances Exist [Robert Villahermosa]

I recently got assigned a question on one of the MSDN forums about obtaining the Parent Process of a child. This is a fairly often asked question, I’ve seen it on the System.Diagnostics FAQ page. The interesting twist to this however, was that sometimes more than one instance of a particular image name will exist on a machine at a given time. For example, I can launch multiple instances of notepad.exe, some perhaps from cmd.exe and others from explorer.exe. Is there an easy way to get which parent processes started these?

I know there is a way to do this using P/Invokes to a native API contained in toolhelp.dll. I found an article in MSDN about this here: https://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnnetcomp/html/ProcessManager.asp

However, I was curious to see if there was a way to do using strictly managed code.

There is!

It turns out that there is a Performance object called “Process” which contains a counter called “Creating Process ID” that you can view using Perfmon. Looking at this on my local machine, I could see that the multiple instances of the application I wanted the parent for were indexed (notepad, notepad#1, notepad#2). However, looking at this in taskmgr.exe, all I could see were 3 instances of notepad.exe. How can one work around this? I came up with a quick and dirty solution, I query for all the instances of notepad on the machine and use this as the indexer.

It’s easy to get all the processes given a name, using the GetProcessesByName static method on the Process class. Given that info, you know the number of instances on the machine so can index them.

Here’s my sample below, it prompts for a child process name and returns the parent process IDs and names for each instance of named process.

using System;

using System.Diagnostics;

namespace ParentProcess

{

    class Example

    {

        static void Main(string[] args)

        {

            Console.WriteLine("Please Enter the name of the process you'd like the parent for:");

            string procName = Console.ReadLine();

            Process[] procList = Process.GetProcessesByName(procName);

            PerformanceCounter myProcID = new PerformanceCounter("Process", "ID Process", procName);

            PerformanceCounter myParentID = new PerformanceCounter("Process", "Creating Process ID", procName);

            float parentPID = myParentID.NextValue();

            Console.WriteLine("Parent for {0}: PID: {1} Name: {2}", procName, parentPID , Process.GetProcessById((int)parentPID).ProcessName);

            for (int i = 1; i < procList.Length; i++)

            {

                PerformanceCounter myMultiProcID = new PerformanceCounter("Process", "ID Process", procName + "#" + i);

                PerformanceCounter myParentMultiProcID = new PerformanceCounter("Process", "ID Process", procName + "#" + i);

                parentPID = myParentMultiProcID.NextValue();

                Console.WriteLine("Parent for {0}#{1}: PID: {2} Name: {3}", procName, i, parentPID, Process.GetProcessById((int)parentPID).ProcessName);

           }

        }

    }

}

This is somewhat hacky, but it only took a few minutes and I think it would be quite easy to build up an entire process tree like this which would be a neat little utility to write in managed code.