2010-11-05 2 views
17

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

+0

Я не думаю, что вы можете надежно сделать это в версиях Windows после Vista. Какую версию вы используете? –

+0

вы можете использовать WMI для этого –

+0

Что вы подразумеваете под именем процесса - имя EXE? –

ответ

5

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

14

У вас есть другой вариант, который вы можете использовать для получения имен exe текущих процессов (имена процессов, как вы писали). Лучший способ немного зависит от языка программирования, который вы используете, и от других требований. Например, вы можете использовать WMI. Еще одним более старым способом является использование Performance Counters (см. Также An Introduction To Performance Counters). Для того, чтобы получить счетчики значений вы можете просто использовать операции запроса реестра из HKEY_PERFORMANCE_DATA базового ключа (см Retrieving Counter Data)

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

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

Фантастический! Сэкономил мне много времени. Просто примечание: есть утечка памяти, где вы не освобождаете «pspid». Тем не менее, удивительно :-) – Dan

+0

Очень легко «исправить» утечку памяти. Это действительно необходимо, только вы используете код как часть функции. Для этого вам нужно просто сохранить значение 'pspid' после первого цикла в другой переменной (потому что в текущем коде значение будет изменено) и вызовите' free' с указателем. – Oleg

16

Вы можете получить идентификатор процесса и name для все запущенные процессы с использованием API ToolHelp.
Следующий код отобразит 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

вам просто нужно использовать: pe32.dwSize = sizeof (PROCESSENTRY32); перед вызовом Process32First() – hB0

+1

@ hB0 - Пропущено это =) – Cyclonecode

+1

Это действительно круто и намного быстрее, чем техника 'NtQuerySystemInformation'. Есть ли способ получить время создания PID, хотя с помощью этой техники? – Noitidart

Смежные вопросы