从subprocess获取父进程ID

我使用CreateProcess API创build一个subprocess。 从subprocess中,我需要获取父进程ID。

如果我的进程树有一个孩子和一个大孩子。 我也需要从大孩子那里获取最顶级父母的进程ID。

您应该使用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,使用父PI​​D打开父进程并在父进程上再次调用NtQueryInformationProcess

注*严格地说,父进程(创建子进程的进程)实际上并没有被记录。 InheritedFromUniqueProcessId只是给你从哪个属性被继承的过程。 但是这很少是一个问题。

或者,如果您不喜欢Native API,则使用带有TH32CS_SNAPPROCESS CreateToolhelp32Snapshot ,它将为您提供所需的信息,不同之处在于您必须搜索整个列表。

wj32的答案应该做你需要的,但我想我会提到另一种方式,以防别人需要一个不同级别的祖先。 您还可以拍摄快照枚举进程树并导航祖先,直到达到您想要达到的级别,如此处所述。

以下示例获取父进程的进程标识(进程从当前进程启动):

 // 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; } 

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

通信是如何发生的取决于进程是仅仅复制自己(分叉),还是也在执行其他进程。 如果进程只是分叉,父进程只需要设置一个适当的变量。 如果进程正在执行其他程序,则需要查看环境变量或命令行参数来中继信息

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

 #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; }