Подтвердить что ты не робот

Получить имя процесса из идентификатора процесса (win32)

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

4b9b3361

Ответ 1

Вы можете получить идентификатор процесса и 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);
    }
}

Ответ 2

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

Еще одним способом, который можно также использовать, является функция NtQuerySystemInformation с SystemProcessInformation в качестве параметра. EnumProcess и многие другие Windows API используют функцию внутри. Структура SYSTEM_PROCESS_INFORMATION, определенная в документации NtQuerySystemInformation, имеет много "недокументированных", но с многолетних известных полей. Если вы ищете в Интернете для определения структуры, вы оштрафуете полную документацию. Интересно, что статус функции hat не полностью документирован. Эта функция была, по крайней мере, в NT 3.5 (вероятно, и раньше) и может быть хорошо использована сейчас в Windows 7 32- или 64-битной. Чтобы быть точным ниже, вы найдете небольшую 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;
}

Ответ 3

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