我正在寻找一种简单的方法来查找进程树(如Process Explorer所示的工具),使用C#或其他.Net语言。 find另一个进程的命令行参数也是有用的(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更快。 请注意,并非所有您需要的功能都可以正常使用。 对于某些东西,你可能会使用(有些)不受支持的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来做这件事。 以此代码片断为例。 从对象列表及其父对象构建树将是一个相当标准的算法。