C# 在.NET中查找进程树

C# 在.NET中查找进程树,c#,.net,windows,interop,C#,.net,Windows,Interop,我正在寻找一种用C#或其他.NET语言查找流程树(如process Explorer等工具所示)的简单方法。查找另一个进程的命令行参数也很有用(System.Diagnostics.process上的StartInfo对于当前进程以外的进程似乎无效) 我认为这些事情只能通过调用win32 api来完成,但我很高兴被证明是错的。我非常确定,您需要使用WinAPI来实现这一点。请看一个例子。从对象列表及其父对象建立树将是一种相当标准的算法。您也可以尝试查看WMI(例如Win32_进程类) 下面是一个

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


我认为这些事情只能通过调用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" };
    }
}
现在只要把它放进任何树结构中,你就完成了