103 votes

Comment obtenir du processus parent .NET gérés de manière

J'étais à la recherche d'un lot pour la méthode pour obtenir des processus parent .NET, mais n'a trouvé qu'P/Invoke.

175voto

Simon Mourier Points 49585

Voici une solution. Il utilise p/invoke, mais semble bien fonctionner, 32 ou 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;
            }
        }
    }

65voto

Michael Hale Points 655

Ce code fournit une interface agréable pour trouver le processus Parent de l'objet et prend en compte la possibilité de processus multiples avec le même nom:

Utilisation:

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));
    }
}

5voto

Jeremy Murray Points 616

Voici ma essayer à une solution gérée.

Il interroge les compteurs de performances pour tous les processus et renvoie un dictionnaire de l'enfant PID parent PID. Ensuite, vous pouvez consulter le dictionnaire avec le PID de voir vos parents, grands-parents, etc.

Il est exagéré dans la quantité d'informations qu'il reçoit, pour sûr. Se sentir libre pour optimiser.

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;
        }
    }
}    

Dans d'autres nouvelles, j'ai appris beaucoup de compteurs de performance, il y avait sur ma machine: 13401. Vache sacrée.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X