简体   繁体   中英

C#/mono: get list of child processes on Windows and Linux

I have the code below for getting a list of child processes on windows by interop'ing with ntdll. Is there an equivalent to 'NtQueryInformationProcess' on Linux, which get's me the process id of the parent of a specified process (like pbi.InheritedFromUniqueProcessId)? I need the code to run on Linux through Mono so hopefully I am hoping I need to change only the part where I get the parent process ID so the code stays mostly the same as on Windows.

public IList< Process > GetChildren( Process parent )
    {
        List< Process > children = new List< Process >();

        Process[] processes = Process.GetProcesses();
        foreach (Process p in processes)
        {
            ProcessBasicInformation pbi = new ProcessBasicInformation();
            try
            {
                uint bytesWritten;
                NtQueryInformationProcess(p.Handle,
                  0, ref pbi, (uint)Marshal.SizeOf(pbi),
                  out bytesWritten); // == 0 is OK

                if (pbi.InheritedFromUniqueProcessId == parent.Id)
                    children.AddRange(GetChildren(p));
            }
            catch
            {
            }
        }

        return children;
    }

One way of finding all the children of a given process in Linux is to do something like this inside your foreach :

string line;
using (StreamReader reader = new StreamReader ("/proc/" + p.Id + "/stat")) {
      line = reader.ReadLine ();
}
string [] parts = line.Split (new char [] {' '}, 5); // Only interested in field at position 3
if (parts.Legth >= 4) {
    int ppid = Int32.Parse (parts [3]);
    if (ppid == parent.Id) {
         // Found a children
    }
}

For more information on what /proc/[id]/stat contains, see the manual page for 'proc'. You should also add a try/catch around the 'using' because the process might die before we open the file, etc...

Actually, there is an issue with Gonzalo's answer, if the process name has spaces in it. This code works for me:

public static int GetParentProcessId(int processId)
{
    string line;
    using (StreamReader reader = new StreamReader ("/proc/" + processId + "/stat"))
          line = reader.ReadLine ();

    int endOfName = line.LastIndexOf(')');
    string [] parts = line.Substring(endOfName).Split (new char [] {' '}, 4);

    if (parts.Length >= 3) 
    {
        int ppid = Int32.Parse (parts [2]);
        return ppid;
    }

    return -1;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM