получить имя процесса из идентификатора процесса (win32) - PullRequest
18 голосов
/ 05 ноября 2010

Мне нужно получить список всех процессов в системе Windows, включая имена и PID.
EnumProcess может получить список pids, но как мне получить имя процесса из pid?Я не хочу вызывать OpenProcess для процесса, так как это не всегда работает (например, если другой процесс выполняется другим пользователем).

Ответы [ 3 ]

16 голосов
/ 03 декабря 2011

- вы можете получить идентификатор процесса и name для всех запущенных процессов, используя ToolHelp API. Следующий код отображает pid и name для каждого процесса.

void showProcessInformation() {
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if(hSnapshot) {
        PROCESSENTRY32 pe32;
        pe32.dwSize = sizeof(PROCESSENTRY32);
        if(Process32First(hSnapshot, &pe32)) {
            do {
               printf("pid %d %s\n", pe32.th32ProcessID, pe32.szExeFile);
            } while(Process32Next(hSnapshot, &pe32));
         }
         CloseHandle(hSnapshot);
    }
}
14 голосов
/ 06 ноября 2010

У вас есть другая опция, которую вы можете использовать для получения exe-имен запущенных в данный момент процессов (имена процессов, как вы написали). Лучший способ немного зависит от языка программирования, который вы используете, и от других требований. Например, вы можете использовать WMI. Еще один более старый способ - использование счетчиков производительности (см. Также Введение в счетчики производительности ). Чтобы получить значения счетчиков, вы можете просто использовать операции запроса реестра из базового ключа HKEY_PERFORMANCE_DATA (см. Получение данных счетчика )

Еще один способ, который также можно использовать, - это функция NtQuerySystemInformation с SystemProcessInformation в качестве параметра. EnumProcess и многие другие API Windows используют эту функцию для внутреннего использования. Структура SYSTEM_PROCESS_INFORMATION, определенная в документации NtQuerySystemInformation , имеет много «недокументированных», но уже много лет хорошо известных областей. Если вы будете искать в Интернете определение структуры, вы будете оштрафованы на полную документацию. Интересно, что статус функции шляпы не полностью документирован. Эта функция была, по крайней мере, в NT 3.5 (возможно, также и раньше) и теперь может быть хорошо использована в 32- или 64-битной Windows 7. Если быть точным, ниже вы найдете небольшую C-тестовую программу, которая печатает все идентификаторы процессов с соответствующими именами exe (не полный путь exe, только имя файла):

#include <Windows.h>
// one can also use Winternl.h if needed
//#include <Winternl.h> // for UNICODE_STRING and SYSTEM_INFORMATION_CLASS
#include <stdio.h>
#include <tchar.h>

#define STATUS_SUCCESS               ((NTSTATUS)0x00000000L)
#define STATUS_INFO_LENGTH_MISMATCH  ((NTSTATUS)0xC0000004L)

typedef enum _SYSTEM_INFORMATION_CLASS {
    SystemProcessInformation = 5
} SYSTEM_INFORMATION_CLASS;

typedef struct _UNICODE_STRING {
    USHORT Length;
    USHORT MaximumLength;
    PWSTR  Buffer;
} UNICODE_STRING;

typedef LONG KPRIORITY; // Thread priority

typedef struct _SYSTEM_PROCESS_INFORMATION_DETAILD {
    ULONG NextEntryOffset;
    ULONG NumberOfThreads;
    LARGE_INTEGER SpareLi1;
    LARGE_INTEGER SpareLi2;
    LARGE_INTEGER SpareLi3;
    LARGE_INTEGER CreateTime;
    LARGE_INTEGER UserTime;
    LARGE_INTEGER KernelTime;
    UNICODE_STRING ImageName;
    KPRIORITY BasePriority;
    HANDLE UniqueProcessId;
    ULONG InheritedFromUniqueProcessId;
    ULONG HandleCount;
    BYTE Reserved4[4];
    PVOID Reserved5[11];
    SIZE_T PeakPagefileUsage;
    SIZE_T PrivatePageCount;
    LARGE_INTEGER Reserved6[6];
} SYSTEM_PROCESS_INFORMATION_DETAILD, *PSYSTEM_PROCESS_INFORMATION_DETAILD;

typedef NTSTATUS (WINAPI *PFN_NT_QUERY_SYSTEM_INFORMATION)(
  IN       SYSTEM_INFORMATION_CLASS SystemInformationClass,
  IN OUT   PVOID SystemInformation,
  IN       ULONG SystemInformationLength,
  OUT OPTIONAL  PULONG ReturnLength
);

int main()
{
    size_t bufferSize = 102400;
    PSYSTEM_PROCESS_INFORMATION_DETAILD pspid=
        (PSYSTEM_PROCESS_INFORMATION_DETAILD) malloc (bufferSize);
    ULONG ReturnLength;
    PFN_NT_QUERY_SYSTEM_INFORMATION pfnNtQuerySystemInformation = (PFN_NT_QUERY_SYSTEM_INFORMATION)
        GetProcAddress (GetModuleHandle(TEXT("ntdll.dll")), "NtQuerySystemInformation");
    NTSTATUS status;

    while (TRUE) {
        status = pfnNtQuerySystemInformation (SystemProcessInformation, (PVOID)pspid,
                                              bufferSize, &ReturnLength);
        if (status == STATUS_SUCCESS)
            break;
        else if (status != STATUS_INFO_LENGTH_MISMATCH) { // 0xC0000004L
            _tprintf (TEXT("ERROR 0x%X\n"), status);
            return 1;   // error
        }

        bufferSize *= 2;
        pspid = (PSYSTEM_PROCESS_INFORMATION_DETAILD) realloc ((PVOID)pspid, bufferSize);
    }

    for (;;
         pspid=(PSYSTEM_PROCESS_INFORMATION_DETAILD)(pspid->NextEntryOffset + (PBYTE)pspid)) {

        _tprintf (TEXT("ProcessId: %d, ImageFileName: %ls\n"), pspid->UniqueProcessId,
            (pspid->ImageName.Length && pspid->ImageName.Buffer)? pspid->ImageName.Buffer: L"");

        if (pspid->NextEntryOffset == 0) break;
    }

    return 0;
}
5 голосов
/ 05 ноября 2010

CreateToolhelp32Snapshot () даст вам имя процесса (но не путь);кроме этого вам придется вызывать OpenProcess ().Если ваш код выполняется в административном контексте, вы можете включить привилегию SE_DEBUG_NAME, чтобы получить доступ к процессам, запущенным в других контекстах.

...