web-dev-qa-db-ja.com

Win32プロセスはその親のpidをどのように取得できますか?

現在、コマンドラインでpidを子に渡していますが、Win32 APIでこれを行う方法はありますか?あるいは、親が亡くなった場合、誰かが私が渡そうとしているPIDがしばらくして別のプロセスに属しているのではないかという私の恐れを緩和できますか?

34
twk

親プロセスが終了した場合、PIDが別のプロセスに再利用される可能性が非常に高く、その可能性が高いことに注意してください。これは標準のWindows操作です。

つまり、親のIDを受け取り、それが本当に親であることが確認できたら、ハンドルを開いて使用する必要があります。

11
shoosh

他の誰かがこの質問に遭遇してコードサンプルを探している場合に備えて、私が取り組んでいる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);
}
50
Jay
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;
}
20
Napalm

これを行うためのより良い方法は、DuplicateHandle()を呼び出して、プロセスハンドルの継承可能な複製を作成することです。次に、子プロセスを作成し、コマンドラインでハンドル値を渡します。 Close親プロセスで複製されたハンドル。子が完了したら、コピーもCloseする必要があります。

20
Peter Ruderman

「あるいは、親が亡くなった場合、誰かが私の通過するpidがしばらくして別のプロセスに属しているのではないかという私の恐れを緩和できますか?」

はい、PIDは再利用できます。 UNIXとは異なり、Windowsは強力な親子関係ツリーを維持しません。

3
user15071