在.NET中找到进程树

我正在寻找一种简单的方法来查找流程树(如Process Explorer之类的工具所示),使用C#或其他.NET语言。 找到另一个进程的命令行参数(System.Diagnostics.Process上的StartInfo对于当前进程以外的进程似乎无效)也很有用。

我认为这些事情只能通过调用win32 api来完成,但我很高兴被certificate是错误的。

如果您不想P / Invoke,您可以使用性能计数器获取父ID:

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" }; } } 

现在只需将它放入任何想要的树结构中,你就完成了。

您还可以尝试查看WMI(例如Win32_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()); } } } } } 

我从最近写的一些代码中删除了这个。 出于您的目的,您可以使用其他技术(例如一次获取多个属性和/或进程)。 但是你明白了。

编辑:例如,构建树所需的父进程ID是“ParentProcessId”属性。

但我想,使用Win32 API会更快。 请注意,并非所有您需要的function都可以正确使用。 对于某些东西,你可以使用(某种程度上)不受支持的NtQueryProcessInformation()函数或来自NTDLL的其他函数。

我不明白你为什么不想p / invoke。 如果你看一下Reflector中的System.Diagnostics,你会发现它在内部使用了p / invokes。 无论如何,Process类没有办法检索进程的父PID。 代替:

结构定义:

 [StructLayout(LayoutKind.Sequential)] struct PROCESS_BASIC_INFORMATION { public int ExitStatus; public int PebBaseAddress; public int AffinityMask; public int BasePriority; public int UniqueProcessId; public int InheritedFromUniqueProcessId; } 

(简化)函数导入:

 [DllImport("ntdll.dll")] static extern int NtQueryInformationProcess( IntPtr ProcessHandle, int ProcessInformationClass, out PROCESS_BASIC_INFORMATION ProcessInformation, int ProcessInformationLength, out int ReturnLength ); 

代码:

 Process p = Process.GetProcessById(1234); PROCESS_BASIC_INFORMATION pbi; int size; NtQueryInformationProcess(p.Handle, 0, out pbi, Marshal.SizeOf(typeof(PROCESS_BASIC_INFORMATION)), out size); // pbi.InheritedFromUniqueProcessId now contains the process' parent PID 

您需要在文件顶部插入这些用法:

 using System.Runtime.InteropServices; using System.Diagnostics; 

如果你想枚举进程,你最好使用NtQuerySystemInformation – 虽然这段代码有点太长了,无法在这里发布。

我很确定你需要使用WinAPI。 请参阅此代码段作为示例。 从对象列表及其父对象构建树将是一种相当标准的算法。