Process "translation"
Here are some neat things to do with processes handles, process ids and window handles.
From process id to process handle
This is quite easy: through the
OpenProcess
API we can obtain a local copy of the handle to the process. Just remember to close it using CloseHandle:
HANDLE processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processId);
CloseHandle(processHandle);
From window handle to process id
Also this is easy, the
GetWindowThreadProcessId API is what we need here:
DWORD processId = 0;
GetWindowThreadProcessId(windowHandle, &processId);
From process handle to process id
This can be done easily through the
GetProcessId function:
HANDLE processHandle =
DWORD processId = GetProcessId(processHandle);
Unfortunately, this function is available only under Windows XP.
There's another way that only requires Windows 2000 and superior, using
GetCurrentProcessId (requires Windows 95)
and
CreateRemoteThread (requires Windows 2000):
HANDLE processHandle =
HANDLE remoteThread = CreateRemoteThread(processHandle, NULL, 0, GetCurrentProcessId, 0, NULL);
WaitForSingleObject(remoteThread, INFINITE);
DWORD processId = 0;
GetExitCodeThread(remoteThread, &processId);
CloseHandle(remoteThread);
Basically, we inject a call to the GetCurrentProcessId function in the process space though CreateRemoteThread, and get the thread's exit code, that is the exit
code of the thread routine, which is GetCurrentProcessId(). Got it? :)
From process id to process executable path
There's an API that can make this procedure easy:
GetModuleFileNameEx:
HANDLE processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processId);
TCHAR exePath[MAX_PATH] = _T("");
GetModuleFileNameEx(processHandle, NULL, exePath, MAX_PATH);
CloseHandle(processHandle);
To use GetModuleFileNameEx, you must link against psapi.lib / libpsapi.a.
But again, this function is available only under Windows XP.
Using the toolhelp library there's a solution for all Windows' version. But, the procedure to get the window handle from the process id is different between Windows XP and older versions of Windows.
Windows XP
HANDLE moduleSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, processID);
MODULEENTRY32 me = {0};
me.dwSize = sizeof(MODULEENTRY32);
Module32First(moduleSnapshot, &me);
CloseHandle(moduleSnapshot);
The obviously thing to do would be enumerate all the processes and compare them to our process id until we find it. But, under Windows XP, the PROCESSENTRY32 structure doesn't set the full path of the executable of the process, just the executable's file name. Instead, the first module of each process has it. So we
- Enumerate all the modules in the process using CreateToolhelp32Snapshot and TH32CS_SNAPMODULE.
- Get the info of the first module using Module32First and the MODULEENTRY32 structure
- The function will copy in the MODULEENTRY32 structure's member variable szExePath the full path of the executable
Windows versions inferior to XP
HANDLE processSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32 pe = {0};
pe.dwSize = sizeof(PROCESSENTRY32);
if (Process32First(processSnapshot, &pe))
{
do {
if (pe.th32ProcessID == processID)
{
break;
}
} while(Process32Next(processSnapshot, &pe));
}
CloseHandle(processSnapshot);
Under windows 9x/ME, the PROCESSENTRY32 has already the full path to the executable (which is stored in the PROCESSENTRY32 structure's member variable
szExeFile). I only need to loop through the open processes to find the right process.
To use the toolhelp library, remember to include the header tlhelp32.h.
From process id to window handle
Using EnumWindows we can enumerate all top windows and use GetWindowThreadProcessId on each of them, until we find the correct window:
typedef struct {
DWORD processId;
HANDLE windowHandle;
} PIDTOHWND;
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
PIDTOHWND pth = (PIDTOHWND)lParam;
DWORD windowProcessId = 0;
GetWindowThreadProcessId(hwnd, windowProcessId);
if (pth->processId == windowProcessId)
{
pth->windowHandle = hwnd;
return FALSE;
}
return TRUE;
}
PIDTOHWND pth = {processId, NULL};
EnumWindows(EnumWindowsProc, pth);
Comments
Paul Sanders wrote:
This is truly terrific. Thans very much for posting.
Regards,
Paul Sanders
http://www.alpinesoft.co.uk
(06.09.2008, 22:11)
NickM wrote:
Great information, many thanks :-)
(29.07.2008, 21:57)
Script by Alex
This page was last modified
56 months, 3 weeks, 3 days and 23 hours ago