C# 在.NET中查找进程树
我正在寻找一种用C#或其他.NET语言查找流程树(如process Explorer等工具所示)的简单方法。查找另一个进程的命令行参数也很有用(System.Diagnostics.process上的StartInfo对于当前进程以外的进程似乎无效)C# 在.NET中查找进程树,c#,.net,windows,interop,C#,.net,Windows,Interop,我正在寻找一种用C#或其他.NET语言查找流程树(如process Explorer等工具所示)的简单方法。查找另一个进程的命令行参数也很有用(System.Diagnostics.process上的StartInfo对于当前进程以外的进程似乎无效) 我认为这些事情只能通过调用win32 api来完成,但我很高兴被证明是错的。我非常确定,您需要使用WinAPI来实现这一点。请看一个例子。从对象列表及其父对象建立树将是一种相当标准的算法。您也可以尝试查看WMI(例如Win32_进程类) 下面是一个
我认为这些事情只能通过调用win32 api来完成,但我很高兴被证明是错的。我非常确定,您需要使用WinAPI来实现这一点。请看一个例子。从对象列表及其父对象建立树将是一种相当标准的算法。您也可以尝试查看WMI(例如Win32_进程类) 下面是一个通过进程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,尽管该代码太长,无法在此处发布。如果您不想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" };
}
}
现在只要把它放进任何树结构中,你就完成了