C# 如何以托管方式获取.NET中的父进程
我一直在寻找在.NET中获取父进程的方法,但只找到了p/Invoke方式。这段代码为查找父进程对象提供了一个很好的界面,并考虑了多个进程使用相同名称的可能性: 用法:C# 如何以托管方式获取.NET中的父进程,c#,process,pinvoke,parent,managed,C#,Process,Pinvoke,Parent,Managed,我一直在寻找在.NET中获取父进程的方法,但只找到了p/Invoke方式。这段代码为查找父进程对象提供了一个很好的界面,并考虑了多个进程使用相同名称的可能性: 用法: Console.WriteLine("ParentPid: " + Process.GetProcessById(6972).Parent().Id); 代码: 公共静态类ProcessExtensions{ 私有静态字符串FindIndexedProcessName(int-pid){ var processName=Proc
Console.WriteLine("ParentPid: " + Process.GetProcessById(6972).Parent().Id);
代码:
公共静态类ProcessExtensions{
私有静态字符串FindIndexedProcessName(int-pid){
var processName=Process.GetProcessById(pid).processName;
var processesByName=Process.GetProcessesByName(processName);
字符串processIndexdName=null;
for(var index=0;index
这里有一个解决方案。它使用p/invoke,但在32或64 cpu的情况下似乎运行良好:
/// <summary>
/// A utility class to determine a process parent.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct ParentProcessUtilities
{
// These members must match PROCESS_BASIC_INFORMATION
internal IntPtr Reserved1;
internal IntPtr PebBaseAddress;
internal IntPtr Reserved2_0;
internal IntPtr Reserved2_1;
internal IntPtr UniqueProcessId;
internal IntPtr InheritedFromUniqueProcessId;
[DllImport("ntdll.dll")]
private static extern int NtQueryInformationProcess(IntPtr processHandle, int processInformationClass, ref ParentProcessUtilities processInformation, int processInformationLength, out int returnLength);
/// <summary>
/// Gets the parent process of the current process.
/// </summary>
/// <returns>An instance of the Process class.</returns>
public static Process GetParentProcess()
{
return GetParentProcess(Process.GetCurrentProcess().Handle);
}
/// <summary>
/// Gets the parent process of specified process.
/// </summary>
/// <param name="id">The process id.</param>
/// <returns>An instance of the Process class.</returns>
public static Process GetParentProcess(int id)
{
Process process = Process.GetProcessById(id);
return GetParentProcess(process.Handle);
}
/// <summary>
/// Gets the parent process of a specified process.
/// </summary>
/// <param name="handle">The process handle.</param>
/// <returns>An instance of the Process class.</returns>
public static Process GetParentProcess(IntPtr handle)
{
ParentProcessUtilities pbi = new ParentProcessUtilities();
int returnLength;
int status = NtQueryInformationProcess(handle, 0, ref pbi, Marshal.SizeOf(pbi), out returnLength);
if (status != 0)
throw new Win32Exception(status);
try
{
return Process.GetProcessById(pbi.InheritedFromUniqueProcessId.ToInt32());
}
catch (ArgumentException)
{
// not found
return null;
}
}
}
//
///用于确定进程父级的实用程序类。
///
[StructLayout(LayoutKind.Sequential)]
公共结构ParentProcessUtilities
{
//这些成员必须与流程基本信息匹配
内部IntPtr储备1;
内部IntPtr PebBaseAddress;
内部IntPtr预留2_0;
内部IntPtr储备2_1;
内部IntPtr UniqueProcessId;
从UniqueProcessId继承的内部IntPtr;
[DllImport(“ntdll.dll”)]
私有静态外部int NtQueryInformationProcess(IntPtr processHandle、int processInformationClass、ref ParentProcessUtilities processInformation、int processInformationLength、out int returnLength);
///
///获取当前进程的父进程。
///
///进程类的实例。
公共静态进程GetParentProcess()
{
返回GetParentProcess(Process.GetCurrentProcess().Handle);
}
///
///获取指定进程的父进程。
///
///进程id。
///进程类的实例。
公共静态进程GetParentProcess(int id)
{
Process=Process.GetProcessById(id);
返回GetParentProcess(process.Handle);
}
///
///获取指定进程的父进程。
///
///这个过程需要处理。
///进程类的实例。
公共静态进程GetParentProcess(IntPtr句柄)
{
ParentProcessUtilities pbi=新的ParentProcessUtilities();
返回长度;
int status=NtQueryInformationProcess(句柄,0,ref-pbi,Marshal.SizeOf(pbi),out-returnLength);
如果(状态!=0)
抛出新的Win32Exception(状态);
尝试
{
返回Process.GetProcessById(pbi.InheritedFromUniqueProcessId.ToInt32());
}
捕获(异常)
{
//找不到
返回null;
}
}
}
以下是我尝试的托管解决方案
它轮询所有进程的性能计数器,并将子PID字典返回给父PID。然后,您可以使用当前PID检查字典,查看您的父母、祖父母等
毫无疑问,它获取的信息量太多了。请随意优化
using System;
using System.Collections.Generic;
using System.Diagnostics;
namespace PidExamples
{
class ParentPid
{
static void Main(string[] args)
{
var childPidToParentPid = GetAllProcessParentPids();
int currentProcessId = Process.GetCurrentProcess().Id;
Console.WriteLine("Current Process ID: " + currentProcessId);
Console.WriteLine("Parent Process ID: " + childPidToParentPid[currentProcessId]);
}
public static Dictionary<int, int> GetAllProcessParentPids()
{
var childPidToParentPid = new Dictionary<int, int>();
var processCounters = new SortedDictionary<string, PerformanceCounter[]>();
var category = new PerformanceCounterCategory("Process");
// As the base system always has more than one process running,
// don't special case a single instance return.
var instanceNames = category.GetInstanceNames();
foreach(string t in instanceNames)
{
try
{
processCounters[t] = category.GetCounters(t);
}
catch (InvalidOperationException)
{
// Transient processes may no longer exist between
// GetInstanceNames and when the counters are queried.
}
}
foreach (var kvp in processCounters)
{
int childPid = -1;
int parentPid = -1;
foreach (var counter in kvp.Value)
{
if ("ID Process".CompareTo(counter.CounterName) == 0)
{
childPid = (int)(counter.NextValue());
}
else if ("Creating Process ID".CompareTo(counter.CounterName) == 0)
{
parentPid = (int)(counter.NextValue());
}
}
if (childPid != -1 && parentPid != -1)
{
childPidToParentPid[childPid] = parentPid;
}
}
return childPidToParentPid;
}
}
}
使用系统;
使用System.Collections.Generic;
使用系统诊断;
名称空间示例
{
类ParentPid
{
静态void Main(字符串[]参数)
{
var childPidToParentPid=GetAllProcessParentPids();
int currentProcessId=Process.GetCurrentProcess().Id;
Console.WriteLine(“当前进程ID:+currentProcessId”);
WriteLine(“父进程ID:+childPidToParentPid[currentProcessId]);
}
公共静态字典GetAllProcessParentPids()
{
var childPidToParentPid=new Dictionary();
var processCounters=new SortedDictionary();
var类别=新绩效计数器类别(“流程”);
//由于基本系统总是运行多个进程,
//不要对单个实例返回进行特殊处理。
var instanceNames=category.GetInstanceNames();
foreach(instanceNames中的字符串t)
{
尝试
{
processCounters[t]=category.GetCounters(t);
}
捕获(无效操作异常)
{
//瞬态过程可能不再存在于
//GetInstanceNames和何时查询计数器。
}
}
foreach(进程计数器中的var kvp)
{
int childPid=-1;
int parentPid=-1;
foreach(kvp.Value中的var计数器)
{
if(“ID Process”.CompareTo(counter.CounterName)==0)
{
childPid=(int)(counter.NextValue());
}
else if(“创建进程ID.CompareTo(counter.CounterName)==0)
{
parentPid=(int)(counter.NextValue());
}
}
if(childPid!=-1&&parentPid!=-1)
{
childPidToParentPid[childPid]=parentPid;
}
}
返回childPidToParentPid;
}
}
}
在ot
using System;
using System.Collections.Generic;
using System.Diagnostics;
namespace PidExamples
{
class ParentPid
{
static void Main(string[] args)
{
var childPidToParentPid = GetAllProcessParentPids();
int currentProcessId = Process.GetCurrentProcess().Id;
Console.WriteLine("Current Process ID: " + currentProcessId);
Console.WriteLine("Parent Process ID: " + childPidToParentPid[currentProcessId]);
}
public static Dictionary<int, int> GetAllProcessParentPids()
{
var childPidToParentPid = new Dictionary<int, int>();
var processCounters = new SortedDictionary<string, PerformanceCounter[]>();
var category = new PerformanceCounterCategory("Process");
// As the base system always has more than one process running,
// don't special case a single instance return.
var instanceNames = category.GetInstanceNames();
foreach(string t in instanceNames)
{
try
{
processCounters[t] = category.GetCounters(t);
}
catch (InvalidOperationException)
{
// Transient processes may no longer exist between
// GetInstanceNames and when the counters are queried.
}
}
foreach (var kvp in processCounters)
{
int childPid = -1;
int parentPid = -1;
foreach (var counter in kvp.Value)
{
if ("ID Process".CompareTo(counter.CounterName) == 0)
{
childPid = (int)(counter.NextValue());
}
else if ("Creating Process ID".CompareTo(counter.CounterName) == 0)
{
parentPid = (int)(counter.NextValue());
}
}
if (childPid != -1 && parentPid != -1)
{
childPidToParentPid[childPid] = parentPid;
}
}
return childPidToParentPid;
}
}
}
public static Process GetParent(this Process process)
{
try
{
using (var query = new ManagementObjectSearcher(
"SELECT * " +
"FROM Win32_Process " +
"WHERE ProcessId=" + process.Id))
{
return query
.Get()
.OfType<ManagementObject>()
.Select(p => Process.GetProcessById((int)(uint)p["ParentProcessId"]))
.FirstOrDefault();
}
}
catch
{
return null;
}
}
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using System.Linq;
using System;
public static class Toolhelp32 {
public const uint Inherit = 0x80000000;
public const uint SnapModule32 = 0x00000010;
public const uint SnapAll = SnapHeapList|SnapModule|SnapProcess|SnapThread;
public const uint SnapHeapList = 0x00000001;
public const uint SnapProcess = 0x00000002;
public const uint SnapThread = 0x00000004;
public const uint SnapModule = 0x00000008;
[DllImport("kernel32.dll")]
static extern bool CloseHandle(IntPtr handle);
[DllImport("kernel32.dll")]
static extern IntPtr CreateToolhelp32Snapshot(uint flags, int processId);
public static IEnumerable<T> TakeSnapshot<T>(uint flags, int id) where T : IEntry, new() {
using(var snap = new Snapshot(flags, id))
for(IEntry entry = new T { }; entry.TryMoveNext(snap, out entry);)
yield return (T)entry;
}
public interface IEntry {
bool TryMoveNext(Toolhelp32.Snapshot snap, out IEntry entry);
}
public struct Snapshot:IDisposable {
void IDisposable.Dispose() {
Toolhelp32.CloseHandle(m_handle);
}
public Snapshot(uint flags, int processId) {
m_handle=Toolhelp32.CreateToolhelp32Snapshot(flags, processId);
}
IntPtr m_handle;
}
}
[StructLayout(LayoutKind.Sequential)]
public struct WinProcessEntry:Toolhelp32.IEntry {
[DllImport("kernel32.dll")]
public static extern bool Process32Next(Toolhelp32.Snapshot snap, ref WinProcessEntry entry);
public bool TryMoveNext(Toolhelp32.Snapshot snap, out Toolhelp32.IEntry entry) {
var x = new WinProcessEntry { dwSize=Marshal.SizeOf(typeof(WinProcessEntry)) };
var b = Process32Next(snap, ref x);
entry=x;
return b;
}
public int dwSize;
public int cntUsage;
public int th32ProcessID;
public IntPtr th32DefaultHeapID;
public int th32ModuleID;
public int cntThreads;
public int th32ParentProcessID;
public int pcPriClassBase;
public int dwFlags;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
public String fileName;
//byte fileName[260];
//public const int sizeofFileName = 260;
}
public static class Extensions {
public static Process Parent(this Process p) {
var entries = Toolhelp32.TakeSnapshot<WinProcessEntry>(Toolhelp32.SnapAll, 0);
var parentid = entries.First(x => x.th32ProcessID==p.Id).th32ParentProcessID;
return Process.GetProcessById(parentid);
}
}
public class TestClass {
public static void TestMethod() {
var p = Process.GetCurrentProcess().Parent();
Console.WriteLine("{0}", p.Id);
}
}
[StructLayout(LayoutKind.Sequential)]
public struct WinModuleEntry:Toolhelp32.IEntry { // MODULEENTRY32
[DllImport("kernel32.dll")]
public static extern bool Module32Next(Toolhelp32.Snapshot snap, ref WinModuleEntry entry);
public bool TryMoveNext(Toolhelp32.Snapshot snap, out Toolhelp32.IEntry entry) {
var x = new WinModuleEntry { dwSize=Marshal.SizeOf(typeof(WinModuleEntry)) };
var b = Module32Next(snap, ref x);
entry=x;
return b;
}
public int dwSize;
public int th32ModuleID;
public int th32ProcessID;
public int GlblcntUsage;
public int ProccntUsage;
public IntPtr modBaseAddr;
public int modBaseSize;
public IntPtr hModule;
//byte moduleName[256];
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string moduleName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
public string fileName;
//byte fileName[260];
//public const int sizeofModuleName = 256;
//public const int sizeofFileName = 260;
}
public class TestClass {
public static void TestMethod() {
var p = Process.GetCurrentProcess().Parent();
Console.WriteLine("{0}", p.Id);
var formatter = new CustomFormatter { };
foreach(var x in Toolhelp32.TakeSnapshot<WinModuleEntry>(Toolhelp32.SnapModule, p.Id)) {
Console.WriteLine(String.Format(formatter, "{0}", x));
}
}
}
public class CustomFormatter:IFormatProvider, ICustomFormatter {
String ICustomFormatter.Format(String format, object arg, IFormatProvider formatProvider) {
var type = arg.GetType();
var fields = type.GetFields();
var q = fields.Select(x => String.Format("{0}:{1}", x.Name, x.GetValue(arg)));
return String.Format("{{{0}}}", String.Join(", ", q.ToArray()));
}
object IFormatProvider.GetFormat(Type formatType) {
return typeof(ICustomFormatter)!=formatType ? null : this;
}
}