Извлечение идентификатора родительского процесса из дочернего процесса - PullRequest
2 голосов
/ 16 марта 2011

Я создаю дочерний процесс, используя CreateProcess API. Из дочернего процесса мне нужно получить идентификатор родительского процесса.

Если у моего дерева процессов есть ребенок и внучатый ребенок. Мне нужно также получить идентификатор процесса у самого старшего родителя у великого ребенка.

Ответы [ 4 ]

6 голосов
/ 16 марта 2011

Вы должны использовать собственный 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 просто дает вам процесс, от которого унаследованы атрибуты.Но это очень редкая проблема.

В качестве альтернативы, если вам не нравится собственный API, используйте CreateToolhelp32Snapshot с TH32CS_SNAPPROCESS, который дает необходимую информацию, за исключениемпридется искать по списку.

1 голос
/ 11 августа 2012

Ответ 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;
}
0 голосов
/ 13 сентября 2014

Вот программа на C для получения идентификатора родительского процесса (всего один цикл для процессов).Функция GetParentProcessId () возвращает идентификатор родительского процесса Windows в своем параметре out «parent_process_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;
}
0 голосов
/ 16 марта 2011

AFAIK, не существует стандартного способа найти процесс дедушки текущего процесса. Поиск родительского процесса - это нормально, но не прародитель. Если вам действительно нужна эта информация, тогда родительский процесс должен информировать своего ребенка о собственном родительском процессе родителя - как в реальной жизни, когда родители должны учить своих детей жизни вообще.

То, как происходит обмен информацией, зависит от того, просто ли процесс сам копирует (разветвляется) или выполняет ли он какой-то другой процесс. Если процессы просто разветвляются, родительский элемент просто должен установить соответствующую переменную. Если процессы выполняют другие программы, вам нужно посмотреть переменную среды или аргумент командной строки, чтобы передать информацию

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...