windows 在 .NET 中找到进程树
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/545449/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
find the process tree in .NET
提问by Robert
I'm looking for an easy way to find the process tree (as shown by tools like Process Explorer), in C# or other .NET language. It would also be useful to find the command-line arguments of another process (the StartInfo on System.Diagnostics.Process seems invalid for process other than the current process).
我正在寻找一种使用 C# 或其他 .NET 语言查找流程树的简单方法(如 Process Explorer 等工具所示)。查找另一个进程的命令行参数也很有用(System.Diagnostics.Process 上的 StartInfo 对于当前进程以外的进程似乎无效)。
I think these things can only be done by invoking the win32 api, but I'd be happy to be proved wrong.
我认为这些事情只能通过调用 win32 api 来完成,但我很高兴被证明是错误的。
回答by DanO
If you don't want to P/Invoke, you can grab the parent Id's with a performance counter:
如果您不想 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" };
}
}
now just put it into whatever tree structure want and you are done.
现在只需将它放入任何想要的树结构中即可。
回答by Christian.K
You could also try to look into WMI (Win32_Process class for example).
您还可以尝试查看 WMI(例如 Win32_Process 类)。
Here is an example to get the command line of a process by its process id:
以下是通过进程 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());
}
}
}
}
}
I ripped this from some code I've recently written. For your purposes you might use other techniques (like getting multiple properties and/or processes at once). But you get the idea.
我从我最近编写的一些代码中提取了它。出于您的目的,您可能会使用其他技术(例如一次获取多个属性和/或进程)。但是你明白了。
EDIT: The parent process id, which you'll need for building the tree is the "ParentProcessId" Property, for example.
编辑:例如,构建树所需的父进程 ID 是“ParentProcessId”属性。
I guess, however, using the Win32 API is faster. Note that not every functionality you required is rightly available there as well. For some stuff you would have resort to the (somewhat) unsupported NtQueryProcessInformation() function or others from NTDLL.
但是,我想使用 Win32 API 会更快。请注意,并非您需要的所有功能都在那里正确可用。对于某些东西,您将不得不求助于(有点)不受支持的 NtQueryProcessInformation() 函数或来自 NTDLL 的其他函数。
回答by wj32
I don't see why you don't want to p/invoke. If you look at System.Diagnostics in Reflector, you'll see that it uses p/invokes internally. Anyway, the Process class does nothave a way of retrieving a process' parent PID. Instead:
我不明白你为什么不想 p/invoke。如果您查看 Reflector 中的 System.Diagnostics,您会发现它在内部使用 p/invokes。无论如何,Process 类无法检索进程的父 PID。反而:
The struct definition:
结构体定义:
[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;
}
The (simplified) function import:
(简化的)函数导入:
[DllImport("ntdll.dll")]
static extern int NtQueryInformationProcess(
IntPtr ProcessHandle,
int ProcessInformationClass,
out PROCESS_BASIC_INFORMATION ProcessInformation,
int ProcessInformationLength,
out int ReturnLength
);
The code:
编码:
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
You'll need to insert these usings at the top of your file:
您需要在文件顶部插入这些用途:
using System.Runtime.InteropServices;
using System.Diagnostics;
If you want to enumerate processes, you'd be better off using NtQuerySystemInformation - although that code is a bit too long to post here.
如果您想枚举进程,最好使用 NtQuerySystemInformation - 尽管该代码有点太长,无法在此处发布。
回答by Noldorin
I'm pretty sure you'll need to go with the WinAPI for this. See this code snippetas an example. It will be a fairly standard algorithm to build up a tree from a list of objects and their parent objects.
我很确定您需要为此使用 WinAPI。请参阅此代码片段作为示例。从对象及其父对象的列表中构建树将是一种相当标准的算法。