当前位置:  开发笔记 > 编程语言 > 正文

如何以托管方式在.NET中获取父进程

如何解决《如何以托管方式在.NET中获取父进程》经验,为你挑选了3个好方法。

我正在寻找很多方法来获取.NET中的父进程,但只找到了P/Invoke方式.



1> Simon Mourie..:

这是一个解决方案.它使用p/invoke,但似乎运行良好,32或64 cpu:

    /// 
    /// A utility class to determine a process parent.
    /// 
    [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);

        /// 
        /// Gets the parent process of the current process.
        /// 
        /// An instance of the Process class.
        public static Process GetParentProcess()
        {
            return GetParentProcess(Process.GetCurrentProcess().Handle);
        }

        /// 
        /// Gets the parent process of specified process.
        /// 
        /// The process id.
        /// An instance of the Process class.
        public static Process GetParentProcess(int id)
        {
            Process process = Process.GetProcessById(id);
            return GetParentProcess(process.Handle);
        }

        /// 
        /// Gets the parent process of a specified process.
        /// 
        /// The process handle.
        /// An instance of the Process class.
        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;
            }
        }
    }


@ justin.m.chase - 已经存在了将近20年,所以我怀疑它将在明天被删除,并且没有任何替代的NT功能可以让我的知识进行父进程,但是,确定,使用风险由您自己承担.
它实际上是托管的,但不能在Windows上运行,而不是Windows.但是,父进程的概念也不可移植,因为它不在.NET Framework本身,所以我认为这不是一个大问题.
大!没有慢速性能计数器.我真的很讨厌"没有管理"的评论.如何使用P/Invoke更好地查询perf计数器.
不幸的是,此功能仅限内部功能 MSDN说这个"[NtQueryInformationProcess可能会在未来版本的Windows中被更改或不可用.应用程序应该使用本主题中列出的备用函数."http://msdn.microsoft.com/en-us/library/windows/desktop/ ms684280(v = vs.85)的.aspx
当我将该方法的性能与其他方法进行比较时,该方法“快至少10倍”。接受的答案打勾:“ 2600657”。这个答案打勾:“ 8454”。
我有一个使用性能计数器来获取父ID的系统。不幸的是,当循环遍历300多个进程并创建性能计数器以获取父ID时,性能非常糟糕。我宁愿避免直接Win32 API调用,但区别是在1秒内停止了服务,而不是使用PerformanceCounter版本花费几分钟。结果,在运行大量服务的服务器上,由于性能原因,这是最适合的主要版本。
NtQueryInformationProcess返回NT状态代码,而不是Win32错误代码。所以`抛出新的Win32Exception(status)`是不合适的。

2> Michael Hale..:

此代码为查找父进程对象提供了一个很好的接口,并考虑了具有相同名称的多个进程的可能性:

用法:

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


这些是一些令人惊讶的命名方法.
不幸的是,当性能计数器类别名称被本地化时(例如,在非英语Windows上),它不起作用.
在我的测试中,这比Simon Mourier的解决方案要慢得多.此外,它不幸地做了某种"带来前进过程"的机制.我不知道为什么.还有其他人经历过这个吗?我正在运行的测试是由Visual Studio创建的安装引导程序EXE,它启动MSIEXEC.exe Windows安装程序.
我建议西蒙的版本除非有迫切的理由,因为性能差异很大.
方法`float.As`在哪里定义?

3> 小智..:

这条路:

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()
        .Select(p => Process.GetProcessById((int)(uint)p["ParentProcessId"]))
        .FirstOrDefault();
    }
  }
  catch
  {
    return null;
  }
}

推荐阅读
mobiledu2402851323
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有