我正在寻找一种简单的方法来查找流程树(如Process Explorer之类的工具所示),使用C#或其他.NET语言。找到另一个进程的命令行参数(System.Diagnostics.Process上的StartInfo对于当前进程以外的进程似乎无效)也很有用。
我认为这些事情只能通过调用win32 api来完成,但我很高兴被证明是错误的。
答案 0 :(得分:5)
如果您不想进行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" };
}
}
现在只需将它放入任何想要的树结构中,你就完成了。
答案 1 :(得分:2)
您也可以尝试查看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的其他函数。
答案 2 :(得分:2)
我不明白为什么你不想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 - 虽然这段代码有点太长了,无法在这里发布。
答案 3 :(得分:-1)
我很确定你需要使用WinAPI。请参阅this code snippet作为示例。从对象列表及其父对象构建树是一种相当标准的算法。