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 (7)
Resources
- MSDN: Process Status API
- MSDN: EnumProcesses function
See also
- Codexpert blog: Listing Processes – Part 1: Introduction