如何以pipe理的方式在.NET中获得父进程
我正在寻找很多方法来获取父进程在.NET中,但只findP / Invoke的方式。
这段代码提供了一个很好的界面来查找父进程对象,并考虑到多个进程具有相同名称的可能性:
用法:
Console.WriteLine("ParentPid: " + Process.GetProcessById(6972).Parent().Id);
码:
public static class ProcessExtensions { private static string FindIndexedProcessName(int pid) { var processName = Process.GetProcessById(pid).ProcessName; var processesByName = Process.GetProcessesByName(processName); string processIndexdName = null; for (var index = 0; index < processesByName.Length; index++) { processIndexdName = index == 0 ? processName : processName + "#" + index; var processId = new PerformanceCounter("Process", "ID Process", processIndexdName); if ((int) processId.NextValue() == pid) { return processIndexdName; } } return processIndexdName; } private static Process FindPidFromIndexedProcessName(string indexedProcessName) { var parentId = new PerformanceCounter("Process", "Creating Process ID", indexedProcessName); return Process.GetProcessById((int) parentId.NextValue()); } public static Process Parent(this Process process) { return FindPidFromIndexedProcessName(FindIndexedProcessName(process.Id)); } }
这是一个解决scheme。 它使用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 or null if an error occurred.</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) return null; try { return Process.GetProcessById(pbi.InheritedFromUniqueProcessId.ToInt32()); } catch (ArgumentException) { // not found return null; } } }
这是我的一个托pipe解决scheme的尝试。
它轮询所有进程的性能计数器,并将子PID的字典返回给父PID。 然后你可以用当前的PID检查字典,看看你的父母,祖父母等等。
当然,它得到了多less信息是矫枉过正的。 随意优化。
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; } } }
在其他消息中,我了解到我的机器上有多less个性能指标:13401。
如果接受P / Invoke,有一个比NtQueryInformationProcess更好的方法:PROCESSENTRY32(CreateToolhelp32Snapshot,Process32First,Process32Next)。 它显示在这篇文章中 。
注意微妙的细节 ,注意家长的PID不一定是创造者的PID,事实上这些可能是完全不相关的,正如PROCESSENTRY32的社区评论所指出的那样。
这条路:
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; } }