windows 从子进程获取父进程 ID

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5321914/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 16:27:00  来源:igfitidea点击:

Fetching parent process Id from child process

cwindowswinapiprocess

提问by Muthukumar Palaniappan

I create a child process using CreateProcess API. From the child process I need to fetch the parent's process id.

我使用 CreateProcess API 创建了一个子进程。我需要从子进程中获取父进程的进程 ID。

If my process tree have a child and a grand child. I need to fetch the top most parent's process id from the grand child as well.

如果我的进程树有一个孩子和一个孙子。我还需要从孙子中获取最顶层的父进程 ID。

回答by wj32

You should use the Native API and GetProcAddressto find the address of NtQueryInformationProcess.

您应该使用本机 API 并GetProcAddress找到NtQueryInformationProcess.

typedef struct _PROCESS_BASIC_INFORMATION
{
    NTSTATUS ExitStatus;
    PPEB PebBaseAddress;
    ULONG_PTR AffinityMask;
    KPRIORITY BasePriority;
    HANDLE UniqueProcessId;
    HANDLE InheritedFromUniqueProcessId;
} PROCESS_BASIC_INFORMATION, *PPROCESS_BASIC_INFORMATION;

NTSYSCALLAPI
NTSTATUS
NTAPI
NtQueryInformationProcess(
    __in HANDLE ProcessHandle,
    __in PROCESS_INFORMATION_CLASS ProcessInformationClass,
    __out_bcount(ProcessInformationLength) PVOID ProcessInformation,
    __in ULONG ProcessInformationLength,
    __out_opt PULONG ReturnLength
    );

PROCESS_BASIC_INFORMATION basicInfo;

NtQueryInformationProcess(NtCurrentProcess(), ProcessBasicInformation, &basicInfo, sizeof(basicInfo), NULL);
// My parent PID (*) is in basicInfo.InheritedFromUniqueProcessId

To get the grandparent PID, open the parent process using the parent PID and call NtQueryInformationProcessagain on the parent process.

要获取祖父 PID,请使用父 PID 打开父进程并NtQueryInformationProcess再次调用父进程。

Note * - Strictly speaking, the parent process (the process which created the child process) is not actually recorded. InheritedFromUniqueProcessIdjust gives you the process from which attributes were inherited. But this is very rarely a problem.

注意 * - 严格来说,父进程(创建子进程的进程)实际上并没有被记录。InheritedFromUniqueProcessId只是为您提供继承属性的过程。但这很少成为问题。

Alternatively, if you don't like the Native API, use CreateToolhelp32Snapshotwith TH32CS_SNAPPROCESS, which gives you the required information, except that you'll have to search through the list.

或者,如果您不喜欢本机 API,请将 CreateToolhelp32Snapshot与 结合使用TH32CS_SNAPPROCESS,它会为您提供所需的信息,但您必须在列表中进行搜索。

回答by Charles Grunwald

wj32's answer should do what you need, but I figured I'd mention another way in case anyone else needs a ancestor at a different level. You can also take a snapshot enumerate the process tree and navigate the ancestors until you reach whatever level you're looking to reach as explained here.

wj32 的答案应该可以满足您的需求,但我想我会提到另一种方式,以防其他人需要不同级别的祖先。您也可以拍摄快照枚举进程树,直到你达到什么水平,你正在寻找可达解释导航祖先在这里

The following example gets the process ID of the parent process (the process started the current one):

以下示例获取父进程的进程 ID(该进程启动了当前进程):

// Speed up build process with minimal headers.
#define WIN32_LEAN_AND_MEAN
#define VC_EXTRALEAN

#include <tchar.h>
#include <windows.h>
#include <tlhelp32.h>
#include <stdio.h>

/* Macros for prettier code. */
#ifndef MAX_PATH
#   define MAX_PATH _MAX_PATH
#endif

// Search each process in the snapshot for id.
BOOL FindProcessID(HANDLE snap, DWORD id, LPPROCESSENTRY32 ppe)
{
    BOOL fOk;
    ppe->dwSize = sizeof(PROCESSENTRY32);
    for (fOk = Process32First( snap, ppe ); fOk; fOk = Process32Next( snap, ppe ))
        if (ppe->th32ProcessID == id)
            break;
    return fOk;
}

// Obtain the process and thread identifiers of the parent process.
BOOL ParentProcess(LPPROCESS_INFORMATION ppi)
{
    HANDLE hSnap;
    PROCESSENTRY32 pe;
    THREADENTRY32   te;
    DWORD id = GetCurrentProcessId();
    BOOL fOk;

    hSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS|TH32CS_SNAPTHREAD, id );

    if (hSnap == INVALID_HANDLE_VALUE)
        return FALSE;

    FindProcessID( hSnap, id, &pe );
    if (!FindProcessID( hSnap, pe.th32ParentProcessID, &pe ))
    {
        CloseHandle( hSnap );
        return FALSE;
    }

    te.dwSize = sizeof(te);
    for (fOk = Thread32First( hSnap, &te ); fOk; fOk = Thread32Next( hSnap, &te ))
        if (te.th32OwnerProcessID == pe.th32ProcessID)
            break;

    CloseHandle( hSnap );

    ppi->dwProcessId = pe.th32ProcessID;
    ppi->dwThreadId = te.th32ThreadID;

    return fOk;
}

int _tmain(int argc, _TCHAR* argv[])
{
    PROCESS_INFORMATION parentInformation;
    if(!ParentProcess(&parentInformation)) {
        _tprintf(TEXT("Fatal: Could not get parent information.\n"));
        return 1;
    }
    _tprintf(TEXT("Parent Process ID: %ul\n"), parentInformation.dwProcessId);
    return 0;
}

回答by Aurélien

Here is a C program to get the parent process id (with only one loop on processes in total). The function GetParentProcessId() returns the Windows parent process id in its out parameter "parent_process_id".

这是一个获取父进程 ID 的 C 程序(总共只有一个进程循环)。函数 GetParentProcessId() 在其输出参数“parent_process_id”中返回 Windows 父进程 ID。

#include <windows.h>
#include <tlhelp32.h>
#include <stdio.h>

// Find a process with a given id in a snapshot
BOOL FindProcessID(HANDLE snap, DWORD id, LPPROCESSENTRY32 ppe)
{
  BOOL res;
  ppe->dwSize = sizeof(PROCESSENTRY32); // (mandatory)
  res = Process32First(snap, ppe); 
  while (res) {
    if (ppe->th32ProcessID == id) {
      return TRUE;
    }
    res = Process32Next(snap, ppe);
  }
  return FALSE;
}

// Get the parent process id of the current process
BOOL GetParentProcessId(DWORD* parent_process_id)
{
  HANDLE hSnap;
  PROCESSENTRY32 pe;
  DWORD current_pid = GetCurrentProcessId();

  // Take a snapshot of all Windows processes
  hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  if (INVALID_HANDLE_VALUE == hSnap) {
    return FALSE;
  }

  // Find the current process in the snapshot
  if (!FindProcessID(hSnap, current_pid, &pe)) {
    return FALSE;
  }

  // Close the snapshot
  if (!CloseHandle(hSnap)) {
    return FALSE;    
  }

  *parent_process_id = pe.th32ParentProcessID;
  return TRUE;
}

回答by Jonathan Leffler

AFAIK, there is no standard way to find the grandparent process of the current process. Finding the parent process is normal, but not the grandparent. If you really need that information, then the parent process has to educate their child about the parent's own parent process - rather like real life where parents have to teach their kids about life in general.

AFAIK,没有找到当前进程的祖父进程的标准方法。找到父进程是正常的,但不是祖父进程。如果你真的需要这些信息,那么父进程必须教育他们的孩子关于父母自己的父进程 - 就像现实生活中父母必须教他们的孩子一般的生活一样。

How the communication occurs depends on whether the process is merely replicating itself (forking), or whether it is also executing some other process. If the processes are merely forking, the parent simply needs to set an appropriate variable. If the processes are executing other programs, then you need to look at an environment variable or a command line argument to relay the information

通信如何发生取决于进程是否只是在复制自己(分叉),或者它是否也在执行某个其他进程。如果进程只是分叉,父进程只需要设置一个适当的变量。如果进程正在执行其他程序,那么您需要查看环境变量或命令行参数来传递信息