【问题标题】:Fetching parent process Id from child process从子进程获取父进程ID
【发布时间】:2011-07-16 08:49:29
【问题描述】:

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

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

【问题讨论】:

    标签: c windows winapi process


    【解决方案1】:

    这是一个获取父进程 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;
    }
    

    【讨论】:

      【解决方案2】:

      wj32 的答案应该可以满足您的需求,但我想我会提到另一种方式,以防其他人需要不同级别的祖先。您还可以拍摄快照,枚举流程树并导航祖先,直到达到您希望达到的任何级别,如 here 所述。

      以下示例获取父进程的进程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;
      }
      

      【讨论】:

        【解决方案3】:

        你应该使用 Native 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
        

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

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

        或者,如果您不喜欢 Native API,请使用 CreateToolhelp32SnapshotTH32CS_SNAPPROCESS,这将为您提供所需的信息,但您必须搜索列表。

        【讨论】:

        • 在 MSDN 上,NtQueryInformationProcess 文档提到了 PROCESS_BASIC_INFORMATION,但它没有 InheritedFromUniqueProcessId。这是否特定于某个 Windows 版本? msdn.microsoft.com/en-us/library/windows/desktop/…
        • NtQueryInformationProcess 现在被标记为过时。
        【解决方案4】:

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

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

        【讨论】:

        • 如果我离开祖父母,只想找到父母的进程 ID,我该怎么办。
        • @Beetles:在 Unix 中,你会使用getppid()。如果您的 Windows 机器上有可用的 Unix 服务,那么您也可以在那里使用它。否则,您可能会发现 _getppid() 可用并且有效,但可能还有一个本地 WinAPI 调用可以完成相同的工作 - 我不知道它是什么,而且我的 Google-fu 似乎已经抛弃了我。跨度>
        猜你喜欢
        • 2017-05-23
        • 1970-01-01
        • 2016-01-20
        • 2013-07-18
        • 1970-01-01
        • 2013-08-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多