Search code examples
c++winapiprocesspidenumerate

windows EnumProcesses some process names as <unknown>


Hello I have this sample code running which uses x to print processNames and PIDS of all currently running processes. Only some of them display an actual name though, with others displaying as (as seen in my output image below)

enter image description here

I was wondering if this was expected behavior, and that not all processes have a name (I could see this being the case for minimal background processes), or if I was using the EnumProcesses function incorrectly.

My code is:

#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <psapi.h>
#include <tlhelp32.h>
#include <tchar.h>


//https://learn.microsoft.com/en-us/windows/desktop/psapi/enumerating-all-processes
void PrintProcessNameAndID( DWORD processID ){
    TCHAR szProcessName[MAX_PATH] = TEXT("<unknown>");
    // Get a handle to the process.
    HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processID );
    // Get the process name.
    if (NULL != hProcess ){
        HMODULE hMod;
        DWORD cbNeeded;
        if ( EnumProcessModules( hProcess, &hMod, sizeof(hMod), &cbNeeded) ){
            GetModuleBaseName( hProcess, hMod, szProcessName, sizeof(szProcessName)/sizeof(TCHAR) );
        }
    }
    // Print the process name and identifier.
    _tprintf( TEXT("%s  (PID: %u)\n"), szProcessName, processID );
    // Release the handle to the process.
    CloseHandle( hProcess );
}

//https://learn.microsoft.com/en-us/windows/desktop/psapi/enumerating-all-processes
int main( void ){
    // Get the list of process identifiers.
    DWORD aProcesses[1024], cbNeeded, cProcesses;
    unsigned int i;
    if ( !EnumProcesses( aProcesses, sizeof(aProcesses), &cbNeeded ) ){
        return 1;
    }
    // Calculate how many process identifiers were returned.
    cProcesses = cbNeeded / sizeof(DWORD);
    // Print the name and process identifier for each process.
    //for ( i = 0; i < cProcesses; i++ ){
    for ( i = 0; i < 3; i++ ){
        if( aProcesses[i] != 0 )        {
            _tprintf( TEXT("aProcesses[%u] = %u (process ID)\n"), i, aProcesses[i] );
            PrintProcessNameAndID( aProcesses[i] );
            ListProcessThreads( aProcesses[i] );
        }
    }
    return 0;
}

Solution

  • As stated in documentation, OpenProcess fails for idle and CSRSS processes.

    If the specified process is the Idle process or one of the CSRSS processes, this function fails and the last error code is ERROR_ACCESS_DENIED because their access restrictions prevent user-level code from opening them.

    You have to enable SeDebugPrivilege (and also run your application with admin privileges). Moreover, if your application is compiled as 32-bit, it cannot access 64-bit processes with OpenProcess

    If you just want a list of running processes, use CreateToolhelp32Snapshot to list running processes.

    #define UNICODE
    #include <Windows.h>
    #include <stdio.h>
    #include <psapi.h>
    #include <tlhelp32.h>
    
    int main()
    {
        wprintf(L"Start:\n");
        HANDLE hndl = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS | TH32CS_SNAPMODULE, 0);
        if(hndl)
        {
            PROCESSENTRY32  process = { sizeof(PROCESSENTRY32) };
            Process32First(hndl, &process);
            do
            {
                wprintf(L"%8u, %s\n", process.th32ProcessID, process.szExeFile);
            } while(Process32Next(hndl, &process));
    
            CloseHandle(hndl);
        }
    }
    

    Side note, it is recommended to compile the program as Unicode. Avoid _txxx macros such as _tprintf etc.