2010-11-05 33 views
17

Necesito obtener una lista de todos los procesos en un sistema de Windows incluyendo nombres y PID.
EnumProcess puede obtener una lista de pids, pero ¿cómo obtengo el nombre del proceso del pid? No quiero llamar a OpenProcess en el proceso, ya que no siempre funciona (como si el otro proceso lo ejecuta otro usuario).obtener el nombre del proceso desde el proceso id (win32)

+0

No creo que pueda hacer esto de manera confiable en las versiones de Windows después de Vista. ¿Qué versión está utilizando? –

+0

podría usar WMI para este –

+0

¿Qué quiere decir con el nombre del proceso, el nombre EXE? –

Respuesta

5

CreateToolhelp32Snapshot() le dará el nombre del proceso (pero no la ruta); aparte de eso, tendrá que llamar a OpenProcess(). Si su código se está ejecutando en un contexto administrativo, puede habilitar el privilegio SE_DEBUG_NAME para obtener acceso a los procesos que se ejecutan en otros contextos.

14

Tiene una opción diferente que puede usar para recibir nombres de ejecución de procesos (nombres de procesos como los que escribió). La mejor manera depende un poco del lenguaje de programación que utiliza y de otros requisitos. Por ejemplo, puede usar WMI. Otra forma más antigua es el uso de Performance Counters (consulte también An Introduction To Performance Counters). Para obtener los valores de los contadores sólo puede utilizar las operaciones de consulta de registro de la clave HKEY_PERFORMANCE_DATA base (ver Retrieving Counter Data)

Una forma más que también puede ser bien utilizado es la función NtQuerySystemInformation con SystemProcessInformation como parámetro. EnumProcess y muchas otras API de Windows usan la función internamente. La estructura SYSTEM_PROCESS_INFORMATION definida en la documentación de NtQuerySystemInformation tiene muchos "indocumentados" pero desde hace muchos años campos muy conocidos. Si busca en Internet la definición de la estructura, multará a la documentación completa. Me pregunto si el estado del sombrero de la función no está completo documentado. La función fue al menos en NT 3.5 (probablemente también antes) y ahora se puede usar bien en Windows 7 de 32 o 64 bits. Para ser exactos a continuación encontrará un pequeño programa de prueba C, que imprime todos los identificadores de proceso con los nombres exe correspondiente (no la ruta completa exe, sólo el nombre de archivo):

#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

¡Fantástico! Me ahorro mucho tiempo. Solo una nota al margen: hay una pérdida de memoria en la que no estás liberando "pspid". Aún así es impresionante :-) – Dan

+0

Es muy fácil "arreglar" la pérdida de memoria. Realmente solo es necesario que uses el código como parte de la función. Para hacer esto, basta con guardar el valor de 'pspid' después del primer ciclo en otra variable (porque en el código actual se modificará el valor) y llamar' free' con el puntero. – Oleg

16

que pueda obtener el identificador de proceso y name de todos los procesos en ejecución usando la API ToolHelp.
El siguiente código mostrará pid y name para cada proceso.

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

solo necesita usar: pe32.dwSize = sizeof (PROCESSENTRY32); antes de llamar a Process32First() – hB0

+1

@ hB0 - Perdí ese = = – Cyclonecode

+1

Esto es realmente genial y mucho más rápido que la técnica 'NtQuerySystemInformation'. Sin embargo, ¿hay alguna manera de obtener el tiempo de creación de PID con esta técnica? – Noitidart

Cuestiones relacionadas