c ++ - Proces-id og procesnavne

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg laver et Windows-program, der grundlæggende scanner systemet for at se, om en bestemt proces kører eller ej. Jeg har procesnavnet (AcroRd32.exe) og intet andet.


Fra hvad jeg har læst den nemmeste måde at oprette et øjebliksbillede af alle processer ved at bruge CreateToolhelp32Snapshot og derefter iterere gennem hver proces på udkig efter procesnavnet.


Min ansøgning er høj ydeevne centreret. Så er der en bedre mere effektiv måde at gøre dette på.
Ansøgningen indsamler et øjebliksbillede hvert par sekunder. Iterering gennem 100 s af processer i øjebliksbilledet virker ikke effektivt. Er der en direkte API, der kan finde Processen gennem dens procesnavn (og hent proceshåndtag eller id gennem navnet)?


Jeg har søgt meget uden held og lykke. Har nogen prøvet dette før?

Bedste reference


Den hurtigste måde at scanne efter processer på er via NTDLLs NtQuerySystemInformation-opkald. Det giver dig en liste over navne og proces-id'er for alle processer på systemet med et enkelt opkald (eller mere i sjældne tilfælde, dvs. store # processer). Du kan kombinere NtQuerySystemInformation og bruge en hash til at foretage streng sammenligninger i stedet for at sammenligne hver byte.


// headers @ http://pastebin.com/HWzJYpbv


NtQuerySystemInformation = (\_RT\_NAPI\_QUERYSYSINFO)GetProcAddress(GetModuleHandleA("NTDLL.DLL"), "NtQuerySystemInformation");

    // Get process information buffer
    do {
        // Allocate buffer for process info
        pBuffer = HeapAlloc(hHeap, HEAP\_ZERO\_MEMORY, cbBuffer); 
        if (pBuffer == NULL) {
            // Cannot allocate enough memory for buffer (CRITICAL ERROR)
            return 1;
        }

        // Obtain system process snapshot
        Status = NtQuerySystemInformation(5, pBuffer, cbBuffer, NULL);

        // Allocate bigger buffer for moar data
        if (Status == STATUS\_INFO\_LENGTH\_MISMATCH) {
            HeapFree(hHeap, 0, pBuffer);
            cbBuffer *= 2; // Increase the size of the buffer :-)
        } else if ((Status) != 0x00) {
            // Can't query process information (probably rootkit or anti-virus)
            HeapFree(hHeap, 0, pBuffer);
            return 1;
        }
    } while (Status == STATUS\_INFO\_LENGTH\_MISMATCH);

    // Get pointer to first system process info structure
    pInfo = (PSYSTEM\_PROCESS\_INFORMATION)pBuffer;

    // Loop over each process
    for (;;) {
        // Get process name
        pszProcessName = pInfo->ImageName.Buffer;

        // ... do work. For a fast string compare, calculate a 32-bit hash of the string, then compare to a static hash.
        if(CRC32(pszProcessName) == 0xDEADBEEF /* <- hash of adobe reader process name goez here */) {
            // Found process
        }

        // Load next entry
        if (pInfo->NextEntryOffset == 0)
            break;
        pInfo = (PSYSTEM\_PROCESS\_INFORMATION)(((PUCHAR)pInfo)+ pInfo->NextEntryOffset);
    }


Testet på Windows 2000 - Windows 7 Engelsk udgaver, x64/x86 (undtagen Win XP x64)
Bemærk: Det returnerer alle processer til 32-bit WOW64-processer på 64-bit systemer.

Andre referencer 1


Ingen.


Hver proces har et unikt id men ikke et unikt navn . Der kunne være flere processer med samme navn. Så det er umuligt at få proceshåndtaget ud af sit navn direkte uden at gentage over alle processer.


Internt er alle prcesses forbundet på en eller anden måde, fx i en tilknyttet liste. Selv hvis der var en funktion GetProcessByName(), ville det internt krydse listen for at finde disse processer med dette navn på vegne af dig også. Så det vil ikke gøre en stor forskel i præstationer.


Bortset


Giv et skud til EnumProcesses(), som har mindre overhead og er enklere. Tjek her.


BOOL WINAPI EnumProcesses(
  \_\_out  DWORD *pProcessIds,
  \_\_in   DWORD cb,
  \_\_out  DWORD *pBytesReturned
);


MSDN har et eksempel på dette. [6]