Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

find the process tree in .NET

I'm looking for an easy way to find the process tree (as shown by tools like Process Explorer), in C# or other .NET language. It would also be useful to find the command-line arguments of another process (the StartInfo on System.Diagnostics.Process seems invalid for process other than the current process).

I think these things can only be done by invoking the win32 api, but I'd be happy to be proved wrong.

like image 347
Robert Avatar asked Mar 23 '26 01:03

Robert


2 Answers

If you don't want to P/Invoke, you can grab the parent Id's with a performance counter:

foreach (var p in Process.GetProcesses())
{
   var performanceCounter = new PerformanceCounter("Process", "Creating Process ID", p.ProcessName);
   var parent = GetProcessIdIfStillRunning((int)performanceCounter.RawValue);
   Console.WriteLine(" Process {0}(pid {1} was started by Process {2}(Pid {3})",
              p.ProcessName, p.Id, parent.ProcessName, parent.ProcessId );
}

//Below is helper stuff to deal with exceptions from 
//looking-up no-longer existing parent processes:

struct MyProcInfo
{
    public int ProcessId;
    public string ProcessName;
}

static MyProcInfo GetProcessIdIfStillRunning(int pid)
{
    try
    {
        var p = Process.GetProcessById(pid);
        return new MyProcInfo() { ProcessId = p.Id, ProcessName = p.ProcessName };
    }
    catch (ArgumentException)
    {
        return new MyProcInfo() { ProcessId = -1, ProcessName = "No-longer existant process" };
    }
}

now just put it into whatever tree structure want and you are done.

like image 98
DanO Avatar answered Mar 25 '26 14:03

DanO


You could also try to look into WMI (Win32_Process class for example).

Here is an example to get the command line of a process by its process id:

                using (var mos = new ManagementObjectSearcher(
                    "SELECT CommandLine FROM Win32_Process WHERE ProcessId = " + pid))
                {
                    foreach (var obj in mos.Get())
                    {
                        object data = obj.Properties["CommandLine"].Value;
                        if (data != null)
                        {
                            Console.WriteLine("{0}: commandline = {1}", pid, data.ToString());
                        }
                    }
                }
            }
        }

I ripped this from some code I've recently written. For your purposes you might use other techniques (like getting multiple properties and/or processes at once). But you get the idea.

EDIT: The parent process id, which you'll need for building the tree is the "ParentProcessId" Property, for example.

I guess, however, using the Win32 API is faster. Note that not every functionality you required is rightly available there as well. For some stuff you would have resort to the (somewhat) unsupported NtQueryProcessInformation() function or others from NTDLL.

like image 31
Christian.K Avatar answered Mar 25 '26 14:03

Christian.K



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!