I'm using Enumprocesses( lpidProcess, cb, lpcbNeeded ) to determine running ProcessIds. How do I subset this list to contain only "Applications", those processes that display on the Task Manager Applications tab?
Thanks in advance.
Per How does Task Manager categorize processes as App, Background Process, or Windows Process? on MSDN:
If the process has a visible window, then Task Manager calls it an "App".
If the process is marked as critical, then Task Manager calls it a "Windows Process".
Otherwise, Task Manager calls it a "Background Process".
So, given a process ID, you can check if it has any visible windows by calling EnumWindows(), where the callback function calls GetWindowThreadProcessId() to check if each window belongs to the process, and IsWindowVisible() to check if each window is visible.
For example:
struct myFindInfo
{
DWORD processID;
bool found;
};
static BOOL CALLBACK findVisibleWindowProc(HWND hwnd, LPARAM lParam)
{
myFindInfo *fi = reinterpret_cast<myFindInfo*>(lParam);
DWORD pid;
GetWindowThreadProcessId(hwnd, &pid);
if ((pid == fi->processID) && IsWindowVisible(hwnd))
{
fi->found = true;
return FALSE;
}
return TRUE;
}
bool isApplicationProcess(DWORD processID)
{
findInfo fi;
fi.processID = processID;
fi.found = false;
EnumWindows(&findVisibleWindowProc, reinterpret_cast<LPARAM>(&fi));
return fi.found;
}
Related
How to get main window handle from process id?
I want to bring this window to the front.
It works well in "Process Explorer".
I checked how .NET determines the main window.
My finding showed that it also uses EnumWindows().
This code should do it similarly to the .NET way:
struct handle_data {
unsigned long process_id;
HWND window_handle;
};
HWND find_main_window(unsigned long process_id)
{
handle_data data;
data.process_id = process_id;
data.window_handle = 0;
EnumWindows(enum_windows_callback, (LPARAM)&data);
return data.window_handle;
}
BOOL CALLBACK enum_windows_callback(HWND handle, LPARAM lParam)
{
handle_data& data = *(handle_data*)lParam;
unsigned long process_id = 0;
GetWindowThreadProcessId(handle, &process_id);
if (data.process_id != process_id || !is_main_window(handle))
return TRUE;
data.window_handle = handle;
return FALSE;
}
BOOL is_main_window(HWND handle)
{
return GetWindow(handle, GW_OWNER) == (HWND)0 && IsWindowVisible(handle);
}
I don't believe Windows (as opposed to .NET) provides a direct way to get that.
The only way I know of is to enumerate all the top level windows with EnumWindows() and then find what process each belongs to GetWindowThreadProcessID(). This sounds indirect and inefficient, but it's not as bad as you might expect -- in a typical case, you might have a dozen top level windows to walk through...
There's the possibility of a mis-understanding here. The WinForms framework in .Net automatically designates the first window created (e.g., Application.Run(new SomeForm())) as the MainWindow. The win32 API, however, doesn't recognize the idea of a "main window" per process. The message loop is entirely capable of handling as many "main" windows as system and process resources will let you create. So, your process doesn't have a "main window". The best you can do in the general case is use EnumWindows() to get all the non-child windows active on a given process and try to use some heuristics to figure out which one is the one you want. Luckily, most processes are only likely to have a single "main" window running most of the time, so you should get good results in most cases.
This is my solution using pure Win32/C++ based on the top answer. The idea is to wrap everything required into one function without the need for external callback functions or structures:
#include <utility>
HWND FindTopWindow(DWORD pid)
{
std::pair<HWND, DWORD> params = { 0, pid };
// Enumerate the windows using a lambda to process each window
BOOL bResult = EnumWindows([](HWND hwnd, LPARAM lParam) -> BOOL
{
auto pParams = (std::pair<HWND, DWORD>*)(lParam);
DWORD processId;
if (GetWindowThreadProcessId(hwnd, &processId) && processId == pParams->second)
{
// Stop enumerating
SetLastError(-1);
pParams->first = hwnd;
return FALSE;
}
// Continue enumerating
return TRUE;
}, (LPARAM)¶ms);
if (!bResult && GetLastError() == -1 && params.first)
{
return params.first;
}
return 0;
}
Though it may be unrelated to your question, take a look at GetGUIThreadInfo Function.
As an extension to Hiale's solution, you could provide a different or modified version that supports processes that have multiple main windows.
First, amend the structure to allow storing of multiple handles:
struct handle_data {
unsigned long process_id;
std::vector<HWND> handles;
};
Second, amend the callback function:
BOOL CALLBACK enum_windows_callback(HWND handle, LPARAM lParam)
{
handle_data& data = *(handle_data*)lParam;
unsigned long process_id = 0;
GetWindowThreadProcessId(handle, &process_id);
if (data.process_id != process_id || !is_main_window(handle)) {
return TRUE;
}
// change these 2 lines to allow storing of handle and loop again
data.handles.push_back(handle);
return TRUE;
}
Finally, amend the returns on the main function:
std::vector<HWD> find_main_window(unsigned long process_id)
{
handle_data data;
data.process_id = process_id;
EnumWindows(enum_windows_callback, (LPARAM)&data);
return data.handles;
}
Just to make sure you are not confusing the tid (thread id) and the pid (process id):
DWORD pid;
DWORD tid = GetWindowThreadProcessId( this->m_hWnd, &pid);
I have a simple (windows) application that launches another application using the CreateProcess function. It then gets the correct hwnd by using EnumWindows and the process id of the newly created process.
After the hwnd has been gained, the 'main loop' of my applications begins. This loop continues until the application started by CreateProcess is no longer running.
Everything works perfectly, until I try to use PeekMessage to peek at the messages being sent to the application I have launched - It seems that no messages at all are being recognized by my application, but the program that was launched (via CreateProcess) is running as normal, doing everything it should..
What I am trying to achieve, is to remove certain messages from being sent to the application, mainly various F-keys (F1, F2..F12 keys), but also, if possible, I would like to change the menu shown in the application (I dont know the technical name for the menu I mean, its the one you see what you click on the application icon in the top right corner) - I want to add a small 'about' option.
If anyone could point out what I am doing wrong within my code, or to a better alternative for stopping certain keypresses from reaching the launched application, I would be very grateful.
Many thanks in advance. :)
Here is the code I currently have:
VOID PerformLaunch(LPWSTR lpAppName, LPTSTR lpCmdLine) {
STARTUPINFO si;
PROCESS_INFORMATION pi;
DWORD dwLoopExitCode = NULL;
BOOL cpBool = FALSE;
BOOL finishedLoop = FALSE;
MSG message = { 0 };
ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
cpBool = CreateProcess(lpAppName, lpCmdLine, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi);
if (!cpBool) {
MessageBox(Game_HWND, L"Could not start process!", L"Error:", MB_OK | MB_ICONERROR);
}
//-- Enumerate windows until Game_HWND && Game_Hook are not NULL.
while (Game_Hook == NULL) {
EnumWindows(MainEnumGameWindProc, pi.dwProcessId);
}
while (!finishedLoop) {
DWORD dwWC = WaitForSingleObject(pi.hProcess, 0);
if ((dwWC == WAIT_FAILED) || (dwWC == WAIT_OBJECT_0)|| (dwWC == WAIT_ABANDONED)) {
DWORD dwExitCode;
GetExitCodeProcess(pi.hProcess, &dwExitCode);
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
dwLoopExitCode = dwExitCode;
finishedLoop = TRUE;
}
else {
if (PeekMessage(&message, Game_HWND, 0, 0, PM_REMOVE)) {
TranslateMessage(&message);
DispatchMessage(&message);
if (WM_QUIT == message.message) {
finishedLoop = TRUE;
break;
}
}
}
}
}
You can't intercept another message loop like that. Remember, that process will be doing its own message pump - it's not okay for you to be dispatching its messages, and I expect things would go very weird if you do.
The correct way is to set a hook. Use the SetWindowsHookEx function to install a hook on that window.
Reference for SetWindowsHookEx
PeekMessage retrieves messages only from the message queue, associated with the its calling thread. Window, which messages you are trying to peek belongs to the different thread, so PeekMessage with its handle will never give you anything. You could either install a hook, or subclass its window procedure.
I'm using ShellExecuteEx to run external application:
SHELLEXECUTEINFO shExInfo = { 0 };
shExInfo.cbSize = sizeof(shExInfo);
shExInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
shExInfo.hwnd = 0;
shExInfo.lpVerb = L"runas"; // Operation to perform
shExInfo.lpFile = windowStringContainingAppPath.c_str(); // Application to start
shExInfo.lpParameters = windowStringContainingAppParameters.c_str(); // Additional parameters
shExInfo.lpDirectory = 0;
shExInfo.nShow = SW_SHOW;
shExInfo.hInstApp = 0;
if(ShellExecuteEx(&shExInfo))
{
WaitForSingleObject(shExInfo.hProcess, INFINITE);
DeleteFile(wsMesh3dx64Parameter.c_str());
CloseHandle(shExInfo.hProcess);
}
Everything works perfectly but there exist an unplanned behaviour of this external app that after closing its main window its process is still active.
This prevents WaitForSingleObject(shExInfo.hProcess, INFINITE); from returning and I have to terminate the process manualy.
Instead I'm looking for a way to replace WaitForSingleObject(shExInfo.hProcess, INFINITE);with a loop that checks if external process owns a window and if not terminate it.
This is what I thought of but if there is a better way please point it out for me.
UPDATE:
Thanks to Robson answer I managed to do what I intended to:
struct Porcess_ID_HWND
{
DWORD processID;
HWND processhWnd;
};
BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam)
{
Porcess_ID_HWND*info = (Porcess_ID_HWND*)lParam;
DWORD processID;
GetWindowThreadProcessId(hWnd, &processID);
if (processID == info->processID){
info->processhWnd = hWnd;
return FALSE;
}
return TRUE;
}
And my loop:
if(ShellExecuteEx(&shExInfo))
{
DWORD dwProcessID = GetProcessId(shExInfo.hProcess);
Porcess_ID_HWND info;
info.processID = dwProcessID;
// wait for window to appear
do
{
info.processhWnd = NULL;
EnumWindows(EnumWindowsProc, (LPARAM)&info);
} while (!info.processhWnd);
// wait for window to close
do
{
info.processhWnd = NULL;
EnumWindows(EnumWindowsProc, (LPARAM)&info);
} while (info.processhWnd);
//WaitForSingleObject(shExInfo.hProcess, INFINITE);
DeleteFile(wsMesh3dx64Parameter.c_str());
CloseHandle(shExInfo.hProcess);
}
found a good answer at http://forums.codeguru.com/showthread.php?392273-RESOLVED-How-to-get-window-s-HWND-from-it-s-process-handle
1)
HAVE: Process ID, NEED: Process handle
Solution: OpenProcess()
2)
HAVE: Process handle, NEED: Process ID
Solution: GetProcessId()
3)
HAVE: Window handle, NEED: Process ID
Solution: GetWindowThreadProcessId()
4)
HAVE: Window handle, NEED: Process handle
Solution: Use 3) and then 1)
5)
HAVE: Process ID, NEED: Window handle
Solution: EnumWindows(), then in the callback function do 3) and check if it matches your process ID.
6)
HAVE: Process handle, NEED: Window handle
Solution: 2) and then 5)
so you are in case 6. then if no window handle's process ID is matched with your shExInfo.hProcess's process ID then shExInfo.hProcess owns no window
I want to detect all the top-level windows in order to send messages to it's Descendants.
How can I do that?
The following code seems to not be detecting Qt top level window, I don't know why.
static BOOL CALLBACK EnumWindowsProc(_In_ HWND hwnd, _In_ LPARAM lParam) {
WORD far wndProcessID;
WORD currentProcessID = GetCurrentProcessId();
std::vector<HWND> *topWindowList = (std::vector<HWND> *)lParam;
if (topWindowList != NULL &&
GetWindowThreadProcessId(hwnd, NULL) == currentProcessID) {
printf("Found a top level window");
fflush(stdout);
topWindowList->push_back(hwnd);
}
return TRUE;
}
void enumAllDesktopChildWindow() {
std::vector<HWND> topWindowList;
EnumChildWindows(GetDesktopWindow(), EnumWindowsProc, LPARAM(&topWindowList));
}
First, the GetWindowThreadProcessId API returns a Thread ID (TID) not a Process ID (PID)
Second, if you want to enumerate all top-level Windows, you should use EnumWindows, not EnumChildWindows. If you want to use EnumChildWindows, pass NULL as the first parameter.
How to get main window handle from process id?
I want to bring this window to the front.
It works well in "Process Explorer".
I checked how .NET determines the main window.
My finding showed that it also uses EnumWindows().
This code should do it similarly to the .NET way:
struct handle_data {
unsigned long process_id;
HWND window_handle;
};
HWND find_main_window(unsigned long process_id)
{
handle_data data;
data.process_id = process_id;
data.window_handle = 0;
EnumWindows(enum_windows_callback, (LPARAM)&data);
return data.window_handle;
}
BOOL CALLBACK enum_windows_callback(HWND handle, LPARAM lParam)
{
handle_data& data = *(handle_data*)lParam;
unsigned long process_id = 0;
GetWindowThreadProcessId(handle, &process_id);
if (data.process_id != process_id || !is_main_window(handle))
return TRUE;
data.window_handle = handle;
return FALSE;
}
BOOL is_main_window(HWND handle)
{
return GetWindow(handle, GW_OWNER) == (HWND)0 && IsWindowVisible(handle);
}
I don't believe Windows (as opposed to .NET) provides a direct way to get that.
The only way I know of is to enumerate all the top level windows with EnumWindows() and then find what process each belongs to GetWindowThreadProcessID(). This sounds indirect and inefficient, but it's not as bad as you might expect -- in a typical case, you might have a dozen top level windows to walk through...
There's the possibility of a mis-understanding here. The WinForms framework in .Net automatically designates the first window created (e.g., Application.Run(new SomeForm())) as the MainWindow. The win32 API, however, doesn't recognize the idea of a "main window" per process. The message loop is entirely capable of handling as many "main" windows as system and process resources will let you create. So, your process doesn't have a "main window". The best you can do in the general case is use EnumWindows() to get all the non-child windows active on a given process and try to use some heuristics to figure out which one is the one you want. Luckily, most processes are only likely to have a single "main" window running most of the time, so you should get good results in most cases.
This is my solution using pure Win32/C++ based on the top answer. The idea is to wrap everything required into one function without the need for external callback functions or structures:
#include <utility>
HWND FindTopWindow(DWORD pid)
{
std::pair<HWND, DWORD> params = { 0, pid };
// Enumerate the windows using a lambda to process each window
BOOL bResult = EnumWindows([](HWND hwnd, LPARAM lParam) -> BOOL
{
auto pParams = (std::pair<HWND, DWORD>*)(lParam);
DWORD processId;
if (GetWindowThreadProcessId(hwnd, &processId) && processId == pParams->second)
{
// Stop enumerating
SetLastError(-1);
pParams->first = hwnd;
return FALSE;
}
// Continue enumerating
return TRUE;
}, (LPARAM)¶ms);
if (!bResult && GetLastError() == -1 && params.first)
{
return params.first;
}
return 0;
}
Though it may be unrelated to your question, take a look at GetGUIThreadInfo Function.
As an extension to Hiale's solution, you could provide a different or modified version that supports processes that have multiple main windows.
First, amend the structure to allow storing of multiple handles:
struct handle_data {
unsigned long process_id;
std::vector<HWND> handles;
};
Second, amend the callback function:
BOOL CALLBACK enum_windows_callback(HWND handle, LPARAM lParam)
{
handle_data& data = *(handle_data*)lParam;
unsigned long process_id = 0;
GetWindowThreadProcessId(handle, &process_id);
if (data.process_id != process_id || !is_main_window(handle)) {
return TRUE;
}
// change these 2 lines to allow storing of handle and loop again
data.handles.push_back(handle);
return TRUE;
}
Finally, amend the returns on the main function:
std::vector<HWD> find_main_window(unsigned long process_id)
{
handle_data data;
data.process_id = process_id;
EnumWindows(enum_windows_callback, (LPARAM)&data);
return data.handles;
}
Just to make sure you are not confusing the tid (thread id) and the pid (process id):
DWORD pid;
DWORD tid = GetWindowThreadProcessId( this->m_hWnd, &pid);