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 (3)

  1. Drew says:

    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

  2. Toffer says:

    definatly like the size of your solution better. If we weren’t trying to avoid using WMI I would probably use it. 😉

  3. RM says:

    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)]