96

.NET で親プロセスを取得する方法をいろいろ探しましたが、P/Invoke の方法しか見つかりませんでした。

4

7 に答える 7

159

これが解決策です。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;
        }
    }
}
于 2010-07-27T17:09:02.407 に答える
64

This code provides a nice interface for finding the Parent process object and takes into account the possibility of multiple processes with the same name:

Usage:

Console.WriteLine("ParentPid: " + Process.GetProcessById(6972).Parent().Id);

Code:

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));
    }
}
于 2010-02-25T17:53:29.540 に答える
11

こちらです:

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;
  }
}
于 2017-09-21T14:12:11.283 に答える
5

これがマネージド ソリューションでの私の試みです。

すべてのプロセスのパフォーマンス カウンターをポーリングし、子 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;
        }
    }
}    

別のニュースとして、自分のマシンに 13401 というパフォーマンス カウンターがいくつあるかを知りました。

于 2011-08-18T22:57:37.027 に答える
3

P/Invoke を受け入れる場合は、NtQueryInformationProcess よりも文書化されたより良い方法があります。つまり、PROCESSENTRY32 (CreateToolhelp32Snapshot、Process32First、Process32Next) です。この投稿に示されています。

PROCESSENTRY32 のコミュニティ コメントで指摘されているよう に、微妙な詳細に注意を払い、親 PID が作成者 PID であるとは限らないことに注意してください。

于 2014-10-01T09:46:38.100 に答える