如何获得应用程序的父进程的PID

时间:2021-11-01 15:23:33

My winform application is launched by another application (the parent), i need determine the pid of the application wich launch my application using c#.

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

4 个解决方案

#1


60  

WMI is the easier way to do this in C#. The Win32_Process class has the ParentProcessId property. Here's an example:

在c#中,WMI是更简单的方法。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();
    }
}

Output when run from Visual Studio:

从Visual Studio运行时输出:

I was started by devenv

我是devenv创立的

#2


8  

Using Brian R. Bondy's answer as a guide, as well as what is on PInvoke.net, and some Reflector output, I have produced this, for use in LinqPad MyExtensions:

使用Brian R. Bondy的答案作为指南,以及PInvoke.net上的内容,以及一些反射器输出,我已经制作了这个,用于LinqPad MyExtensions:

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

#3


6  

If you have control over the parent application, you could modify the parent to pass its PID to the child when it launches the process.

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

#4


2  

Check the th32ParentProcessID member of a CreateToolhelp32Snapshot enumeration.

检查CreateToolhelp32Snapshot枚举的th32ParentProcessID成员。

For an example of how to do this see my post here.

举个例子,看看我在这里的帖子。

Since you are using C# though you'll need to use DllImports. In the linked post there are MSDN pages for each for the functions you need. At the bottom of each MSDN page they have the code for DllImport for C#.

因为您正在使用c#,但是您需要使用DllImports。在链接的帖子中,有针对您需要的功能的MSDN页面。在每个MSDN页面的底部都有c#的DllImport代码。

There is also an easier way using managed code only but it doesn't work if you have the more than one process name started by different applications.

也有一种更简单的方法只使用托管代码,但是如果您有多个进程名由不同的应用程序启动,那么它就不能工作。

#1


60  

WMI is the easier way to do this in C#. The Win32_Process class has the ParentProcessId property. Here's an example:

在c#中,WMI是更简单的方法。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();
    }
}

Output when run from Visual Studio:

从Visual Studio运行时输出:

I was started by devenv

我是devenv创立的

#2


8  

Using Brian R. Bondy's answer as a guide, as well as what is on PInvoke.net, and some Reflector output, I have produced this, for use in LinqPad MyExtensions:

使用Brian R. Bondy的答案作为指南,以及PInvoke.net上的内容,以及一些反射器输出,我已经制作了这个,用于LinqPad MyExtensions:

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

#3


6  

If you have control over the parent application, you could modify the parent to pass its PID to the child when it launches the process.

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

#4


2  

Check the th32ParentProcessID member of a CreateToolhelp32Snapshot enumeration.

检查CreateToolhelp32Snapshot枚举的th32ParentProcessID成员。

For an example of how to do this see my post here.

举个例子,看看我在这里的帖子。

Since you are using C# though you'll need to use DllImports. In the linked post there are MSDN pages for each for the functions you need. At the bottom of each MSDN page they have the code for DllImport for C#.

因为您正在使用c#,但是您需要使用DllImports。在链接的帖子中,有针对您需要的功能的MSDN页面。在每个MSDN页面的底部都有c#的DllImport代码。

There is also an easier way using managed code only but it doesn't work if you have the more than one process name started by different applications.

也有一种更简单的方法只使用托管代码,但是如果您有多个进程名由不同的应用程序启动,那么它就不能工作。