Share via


solution to getting the parent process

In case anyone was interested, I did end up figuring out how to get the parent process of a given process...here's the code I used to do it...  just to make note of it, wttsvc is a test harness which launches my test processes, there will only be one of them.  For this test example I had it launch notepad, and for use with this example it works perfectly fine unless there is more than one instance of notepad up and running.  :)

class Program
{
    static void Main(string[] args)
{
        Process[] myProc = Process.GetProcessesByName("notepad");
        Process[] wttProc = Process.GetProcessesByName("wttsvc");

        PROCESSENTRY32 myProcEntry = new PROCESSENTRY32();

IntPtr handleToSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

        try
        {
            if (Process32First(handleToSnapshot, myProcEntry))
            {
                if (myProc[0].Id == myProcEntry.ProcID && wttProc[0].Id == myProcEntry.ParentProcID)
                {
                    Console.WriteLine("Process ID : {0}", myProcEntry.ProcID);
                    Console.WriteLine("Parent Process ID: {0}", myProcEntry.ParentProcID);
                }
            }
            else
{
                Console.WriteLine("Failed with Wind32 error code {0}", Marshal.GetLastWin32Error());
            }

            while (Process32Next(handleToSnapshot, myProcEntry))
            {
                if (myProc[0].Id == myProcEntry.ProcID && wttProc[0].Id == myProcEntry.ParentProcID)
                {
                    Console.WriteLine("Process ID : {0}", myProcEntry.ProcID);
                    Console.WriteLine("Parent Process ID: {0}", myProcEntry.ParentProcID);
                }
            }
        }
        catch (System.IndexOutOfRangeException ex)
        {
            Console.WriteLine("Notepad or WTTSvc was not running. Exception message: {0}", ex.Message);
        }
    }

    [DllImport("kernel32", SetLastError=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)]
    static extern IntPtr CreateToolhelp32Snapshot([In]UInt32 dwFlags, [In]UInt32 th32ProcessID);

    [DllImport("kernel32", SetLastError = true, CharSet=System.Runtime.InteropServices.CharSet.Auto)]
    static extern bool Process32First([In]IntPtr hSnapshot, [In, Out]PROCESSENTRY32 lppe);

    [DllImport("kernel32", SetLastError = true, CharSet=System.Runtime.InteropServices.CharSet.Auto)]
    static extern bool Process32Next([In]IntPtr hSnapshot, [In, Out]PROCESSENTRY32 lppe);

    const UInt32 TH32CS_SNAPPROCESS = 0x00000002;
    const int MAX_PATH = 260;

    [StructLayout(LayoutKind.Sequential)]
    class PROCESSENTRY32
{
        UInt32 dwSize = (UInt32)Marshal.SizeOf(typeof(PROCESSENTRY32));
        UInt32 cntUsage = 0;
        UInt32 th32ProcessID = 0;
        IntPtr th32DefaultHeapID = IntPtr.Zero;
        UInt32 th32ModuleID = 0;
        UInt32 cntThreads = 0;
        UInt32 th32ParentProcessID = 0;
        Int32 pcPriClassBase = 0;
        UInt32 dwFlags = 0;
        [MarshalAs(UnmanagedType.ByValTStr,SizeConst=MAX_PATH*sizeof(char))]
        string szExeFile;

        public UInt32 ProcID
        {
            get
{
                return th32ProcessID;
            }
        }

        public UInt32 ParentProcID
        {
            get
{
                return th32ParentProcessID;
            }
        }
    }
}

Comments

  • Anonymous
    July 21, 2005
    Ah. That's much simpler than using WMI. ;-)
    Here's a snippet of VB Script that does the same thing.

    Set objWMIService = GetObject("winmgmts:.rootCIMV2")
    Set colItems = objWMIService.ExecQuery("SELECT * FROM Win32_Process WHERE Name='notepad.exe'")
    For Each objItem in colItems
    WScript.Echo "Process ID: " & objItem.ProcessId
    WScript.Echo "Parent Process ID: " & objItem.ParentProcessId
    Next
  • Anonymous
    July 25, 2005
    definatly like the size of your solution better. If we weren't trying to avoid using WMI I would probably use it. ;)
  • Anonymous
    April 14, 2007
    The szExeFile member is marshalled incorrectly. You have to change [StructLayout(LayoutKind.Sequential)] into [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] and [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH * sizeof(char))] into [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH)]