Listing Processes – Part 2: Using PSAPI

A previous article shows how to list running processes from command line. Next, we’ll see how to get a list of processes in our own programs. Let’s start by using Process Status API (PSAPI).

Using PSAPI

Here is an example that calls EnumProcesses PSAPI function, then fills an array with the found process identifiers.

#include <Psapi.h>
#pragma comment(lib, "Psapi.lib")
// ...

DWORD CDemoDlg::PSAPI_EnumProcesses(CDWordArray& arrProcessIds, DWORD dwMaxProcessCount)
{
    DWORD dwRet = NO_ERROR;
    arrProcessIds.RemoveAll();

    DWORD *pProcessIds = new DWORD[dwMaxProcessCount];
    DWORD cb = dwMaxProcessCount * sizeof(DWORD);
    DWORD dwBytesReturned = 0;

    // call PSAPI EnumProcesses
    if(::EnumProcesses(pProcessIds, cb, &dwBytesReturned))
    {
        // fill the array with returned process IDs
        const int nSize = dwBytesReturned / sizeof(DWORD);
        arrProcessIds.SetSize(nSize);
        for(int nIndex = 0; nIndex < nSize; nIndex++)
        {
            arrProcessIds[nIndex] = pProcessIds[nIndex];
        }
    }
    else
    {
        dwRet = ::GetLastError();
    }
    delete []pProcessIds;
    return dwRet;
}

Once having the process identifiers, we can call OpenProcess to get process handles, then use the handles in other functions which get info about processes. Next example fills a listview control with process identifiers, names and image file paths.

void CDemoDlg::_FillProcessesList()
{
    // clear the listvie control
    m_listProcesses.DeleteAllItems();

    // get an array of process IDs
    CDWordArray arrProcessIds;
    VERIFY(NO_ERROR == PSAPI_EnumProcesses(arrProcessIds, 1024));
    const int nSize = arrProcessIds.GetSize();

    // fill the listview control
    for(int nIndex = 0; nIndex < nSize; nIndex++)
    {
        DWORD dwProcessId = arrProcessIds[nIndex];
        // get the process handle
        HANDLE hProcess = ::OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, dwProcessId);
        if(NULL != hProcess)
        {
            // insert new item in the list
            const int nItemCount = m_listProcesses.GetItemCount();
            m_listProcesses.InsertItem(nItemCount, NULL);

            // format process ID
            CString strProcessID;
            strProcessID.Format(_T("%u"), dwProcessId);

            // get executable file path (in device form)
            CString strImageFileName;
            ::GetProcessImageFileName(hProcess, CStrBuf(strImageFileName, MAX_PATH), MAX_PATH);

            // get image name
            CString strImageName = ::PathFindFileName(strImageFileName);

            // set subitems text
            m_listProcesses.SetItemText(nItemCount, 0, strProcessID);
            m_listProcesses.SetItemText(nItemCount, 1, strImageName);
            m_listProcesses.SetItemText(nItemCount, 2, strImageFileName);

            // close the process handle
            ::CloseHandle(hProcess);
        }
    }
}

Demo project

The demo project is a simple MFC dialog-based application that uses the above functions.
Download: Listing_Processes_Using_PSAPI.zip (1299 downloads)

Using PSAPI - Demo Application
Using PSAPI – Demo Application

Resources

See also

Leave a Comment