Introduction
A few days back, in one of my projects, I needed to enumerate all the visible windows, and then needed to determine if a given application was running or not. I first struggled a little, but soon found a simple method to do that.
Enumerating the windows
With the EnumWindows
API, I filtered out the visible windows. Next, with GetWindowThreadProcessId
, I found the process ID of that window, and with that, I found the name of the executable file.
Below is the callback function for EnumWindows
:
BOOL CALLBACK CProcessDlg::EnumWindowsProc (HWND hWnd, LPARAM lParam)
{
CProcessDlg *pDlg = (CProcessDlg *)lParam;
int nItem = 0;
TCHAR szWindowText [MAX_PATH];
if (!::IsWindowVisible (hWnd))
return TRUE;
::GetWindowText (hWnd, szWindowText, MAX_PATH);
if (_tcsstr (_T("Program Manager"), szWindowText))
return TRUE;
DWORD dwProcessID;
GetWindowThreadProcessId (hWnd, &dwProcessID);
CString strEXEName = pDlg->GetEXEName (dwProcessID);
nItem = pDlg->m_List.InsertItem (0, szWindowText);
pDlg->m_List.SetItemText (nItem, 1, strEXEName);
return TRUE;
}
Finding module name
The GetEXEName
procedure returns the name of the executable file from its process ID:
#include "psapi.h"
#pragma comment(lib, "psapi.lib")
CString GetEXEName(DWORD dwProcessID)
{
DWORD aProcesses [1024], cbNeeded, cProcesses;
unsigned int i;
if (!EnumProcesses(aProcesses, sizeof(aProcesses), &cbNeeded))
return NULL;
cProcesses = cbNeeded / sizeof(DWORD);
TCHAR szEXEName[MAX_PATH];
for (i = 0; i < cProcesses; i++)
{
if (aProcesses [i] == dwProcessID)
{
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION |
PROCESS_VM_READ, FALSE, dwProcessID);
if (NULL != hProcess)
{
HMODULE hMod;
DWORD cbNeeded;
if(EnumProcessModules(hProcess, &hMod,
sizeof(hMod), &cbNeeded))
{
GetModuleBaseName(hProcess, hMod, szEXEName,
sizeof(szEXEName)/sizeof(TCHAR));
return CString (szEXEName);
}
}
}
}
return NULL;
}
Conclusion
The code is very easy to understand and follow, please see the demo project if you have any trouble using it.
I hope you find it useful.