我使用CreateProcess API创建子进程。从子进程中我需要获取父进程的id。
如果我的进程树有一个孩子和一个大孩子。我还需要从大孩子那里获取最顶级父母的进程ID。
答案 0 :(得分:6)
您应该使用原生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,请将CreateToolhelp32Snapshot与TH32CS_SNAPPROCESS
一起使用,它会为您提供所需的信息,但您必须搜索列表。
答案 1 :(得分:1)
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;
}
答案 2 :(得分:0)
AFAIK,没有标准的方法来查找当前进程的祖父进程。查找父进程是正常的,但不是祖父进程。如果你真的需要那些信息,那么父母的过程必须教育他们的孩子关于父母自己的父母过程 - 而不是现实生活,父母必须教他们的孩子一般的生活。
通信的发生方式取决于流程是仅仅复制自身(分叉),还是执行其他流程。如果这些过程只是分叉,那么父母只需要设置一个合适的变量。如果进程正在执行其他程序,那么您需要查看环境变量或命令行参数来中继信息
答案 3 :(得分:0)
这是一个获取父进程id的C程序(总共只有一个进程循环)。 函数GetParentProcessId()在其out参数&#34; parent_process_id&#34;中返回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;
}