30

我的 winform 应用程序由另一个应用程序(父级)启动,我需要确定使用 C# 启动我的应用程序的应用程序的 pid。

4

4 回答 4

67

WMI 是在 C# 中执行此操作的更简单方法。Win32_Process 类具有 ParentProcessId 属性。这是一个例子:

using System;
using System.Management;  // <=== Add Reference required!!
using System.Diagnostics;

class Program {
    public static void Main() {
        var myId = Process.GetCurrentProcess().Id;
        var query = string.Format("SELECT ParentProcessId FROM Win32_Process WHERE ProcessId = {0}", myId);
        var search = new ManagementObjectSearcher("root\\CIMV2", query);
        var results = search.Get().GetEnumerator();
        results.MoveNext();
        var queryObj = results.Current;
        var parentId = (uint)queryObj["ParentProcessId"];
        var parent = Process.GetProcessById((int)parentId);
        Console.WriteLine("I was started by {0}", parent.ProcessName);
        Console.ReadLine();
    }
}

从 Visual Studio 运行时的输出:

我是由 devenv 发起的

于 2010-03-28T14:43:37.917 回答
11

使用 Brian R. Bondy 的回答作为指导,以及 PInvoke.net 上的内容和一些 Reflector 输出,我制作了这个,用于 LinqPad MyExtensions

using Microsoft.Win32.SafeHandles;
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;

static class ProcessExtensions
{
    public static int ParentProcessId(this Process process)
    {
      return ParentProcessId(process.Id);
    }
    public static int ParentProcessId(int Id)
    {
        PROCESSENTRY32 pe32 = new PROCESSENTRY32{};
        pe32.dwSize = (uint)Marshal.SizeOf(typeof(PROCESSENTRY32));
        using(var hSnapshot = CreateToolhelp32Snapshot(SnapshotFlags.Process, (uint)Id))
        {
            if(hSnapshot.IsInvalid)
                throw new Win32Exception();

            if(!Process32First(hSnapshot, ref pe32))
            {
                int errno = Marshal.GetLastWin32Error();
                if(errno == ERROR_NO_MORE_FILES)
                    return -1;
                throw new Win32Exception(errno);
            }    
            do {
                    if(pe32.th32ProcessID == (uint)Id)
                        return (int)pe32.th32ParentProcessID;
            } while(Process32Next(hSnapshot, ref pe32));
        }
        return -1;
    }
    private const int ERROR_NO_MORE_FILES = 0x12;
    [DllImport("kernel32.dll", SetLastError=true)]
    private static extern SafeSnapshotHandle CreateToolhelp32Snapshot(SnapshotFlags flags, uint id);
    [DllImport("kernel32.dll", SetLastError=true)]
    private static extern bool Process32First(SafeSnapshotHandle hSnapshot, ref PROCESSENTRY32 lppe);
    [DllImport("kernel32.dll", SetLastError=true)]
    private static extern bool Process32Next(SafeSnapshotHandle hSnapshot, ref PROCESSENTRY32 lppe);

    [Flags]
    private enum SnapshotFlags : uint
    {
        HeapList = 0x00000001,
        Process  = 0x00000002,
        Thread   = 0x00000004,
        Module   = 0x00000008,
        Module32 = 0x00000010,
        All      = (HeapList | Process | Thread | Module),
        Inherit  = 0x80000000,
        NoHeaps  = 0x40000000
    }
    [StructLayout(LayoutKind.Sequential)]
    private struct PROCESSENTRY32 
    { 
      public uint dwSize; 
      public uint cntUsage; 
      public uint th32ProcessID; 
      public IntPtr th32DefaultHeapID; 
      public uint th32ModuleID; 
      public uint cntThreads; 
      public uint th32ParentProcessID; 
      public int pcPriClassBase; 
      public uint dwFlags; 
      [MarshalAs(UnmanagedType.ByValTStr, SizeConst=260)] public string szExeFile; 
    };
    [SuppressUnmanagedCodeSecurity, HostProtection(SecurityAction.LinkDemand, MayLeakOnAbort=true)]
    internal sealed class SafeSnapshotHandle : SafeHandleMinusOneIsInvalid
    {
        internal SafeSnapshotHandle() : base(true)
        {
        }

        [SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode=true)]
        internal SafeSnapshotHandle(IntPtr handle) : base(true)
        {
            base.SetHandle(handle);
        }

        protected override bool ReleaseHandle()
        {
            return CloseHandle(base.handle);
        }

        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success), DllImport("kernel32.dll", CharSet=CharSet.Auto, SetLastError=true, ExactSpelling=true)]
        private static extern bool CloseHandle(IntPtr handle);
    }
}
于 2013-05-26T06:33:31.103 回答
7

如果您可以控制父应用程序,则可以修改父应用程序以在启动进程时将其 PID 传递给子应用程序。

于 2010-03-28T04:19:29.753 回答
2

检查 CreateToolhelp32Snapshot 枚举的 th32ParentProcessID 成员。

有关如何执行此操作的示例,请参见我的帖子

由于您使用的是 C#,但您需要使用 DllImports。在链接的帖子中,每个都有您需要的功能的 MSDN 页面。在每个 MSDN 页面的底部,它们都有用于 C# 的 DllImport 的代码。

还有一种仅使用托管代码的更简单方法,但如果您有多个由不同应用程序启动的进程名称,则它不起作用。

于 2010-03-28T04:07:33.893 回答