2008-10-08 99 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; 
}