2008-10-08 101 views
30

我目前正在将命令行上的pid传递给孩子,但是有没有办法在Win32 API中执行此操作?或者,如果父母已经死亡,某人是否可以减轻我对我经过的pid可能属于另一个过程的恐惧?Win32进程如何获取父进程的PID?

+0

当父进程退出时,Windows XP不会重新指定父PID为-1,所以有可能(并且我已经看到这种情况)导致进程树错误。因此,您可以在Process Explorer显示的树中将NOTEPAD.EXE看作IEXPLORE.EXE的父项,这显然是错误的。 – 2012-06-27 21:57:53

回答

8

注意,如果父进程终止,那么很可能甚至有可能PID将被重新用于另一个进程。这是标准的Windows操作。

所以可以肯定的是,一旦你收到父母的身份证,并确定它确实是你的父母,你应该打开一个句柄并使用它。

+0

这是使用OpenProcess()完成的。请参阅以下artur02答案中的链接。 – 2013-04-11 12:37:33

+12

通过额外检查开始时间可以检测到重复使用的PID。真正的父母会在孩子之前有一个开始时间,一个重用的时间 - 之后。 – 2014-10-29 13:05:13

2

“另外,有人可以减轻我的恐惧,如果父母已经去世 我传递 的PID可能会在一段时间后属于另一个进程?”

是的,PID可以重复使用。与UNIX不同,Windows不维护强大的父子关系树。

+1

同样在LINUX上进程ID正在被重用。只是因为pid_t不是无限大小。 MAXPID是2^15。我在一天内多次看到这种情况。另一方面,在Windows中,通过句柄存在强大的父子关系 - 只要您保持句柄处于打开状态,就可以继续参考父进程。 – 2016-01-08 00:00:49

47

为了防止任何人遇到这个问题并且正在寻找代码示例,我最近必须为我正在处理的Python库项目执行此操作。这是我想出了测试/示例代码:

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

int main(int argc, char *argv[]) 
{ 
    int pid = -1; 
    HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); 
    PROCESSENTRY32 pe = { 0 }; 
    pe.dwSize = sizeof(PROCESSENTRY32); 

    //assume first arg is the PID to get the PPID for, or use own PID 
    if (argc > 1) { 
     pid = atoi(argv[1]); 
    } else { 
     pid = GetCurrentProcessId(); 
    } 

    if(Process32First(h, &pe)) { 
     do { 
      if (pe.th32ProcessID == pid) { 
       printf("PID: %i; PPID: %i\n", pid, pe.th32ParentProcessID); 
      } 
     } while(Process32Next(h, &pe)); 
    } 

    CloseHandle(h); 
} 
+0

你有任何机会的蟒蛇版本吗? – 2012-08-29 21:16:45

+1

这种方法可以提供其他地方提到的陈旧的PID,如果您尝试走上父母ID,甚至可能会有周期。 – 2014-09-11 14:01:53

18

一个更好的办法来做到这一点是调用DuplicateHandle()以创建进程句柄的可继承副本。然后创建子进程并在命令行上传递句柄值。 Close父进程中的重复句柄。当孩子完成后,它也需要Close的副本。

19
ULONG_PTR GetParentProcessId() // By Napalm @ NetCore2K 
{ 
ULONG_PTR pbi[6]; 
ULONG ulSize = 0; 
LONG (WINAPI *NtQueryInformationProcess)(HANDLE ProcessHandle, ULONG ProcessInformationClass, 
    PVOID ProcessInformation, ULONG ProcessInformationLength, PULONG ReturnLength); 
*(FARPROC *)&NtQueryInformationProcess = 
    GetProcAddress(LoadLibraryA("NTDLL.DLL"), "NtQueryInformationProcess"); 
if(NtQueryInformationProcess){ 
    if(NtQueryInformationProcess(GetCurrentProcess(), 0, 
    &pbi, sizeof(pbi), &ulSize) >= 0 && ulSize == sizeof(pbi)) 
    return pbi[5]; 
} 
return (ULONG_PTR)-1; 
}