Process ID changes when program is visible or minimized [duplicate] - c++

This question already has answers here:
Name of process for active window in Windows 8/10
(4 answers)
Closed 5 years ago.
I am trying to get the Process ID of a program (PID) but for some odd reason, the PID changes. When the target program (Alarms & Clock) is visible, it gives me the wrong PID while having the program minimized gives me the right PID.
I am guessing that minimizing the target program suspends it's process, thus allowing it to be read. However, simply reading the PID should not be a restriction even when a process is running.
Does anyone have an idea on what am I doing wrong?
Currently Tried Methods:
Ran in Administrative Mode
Compiled for 64 bit
Compiled for 32 bit
ere is a working, concise piece of code that portrays the problem:
#include <iostream>
#include <Windows.h>
#include <string>
int main()
{
std::string window_name = "Alarms & Clock"; //Feel free to replace this with another program
HWND hwnd = FindWindowA(NULL, window_name.c_str());
if (!hwnd)
{
std::cerr << "Error: Could not find window" << std::endl;
return -1;
}
DWORD processID = 0;
GetWindowThreadProcessId(hwnd, &processID);
std::cout << "Process ID: " << processID << std::endl;
std::cin.get();
return 0;
}

I was able to regenerate the problem on my Win/10 with GCC 5.3. I tested it with the "Calculator" app. When the app's window was not minimized I got PID = 14440 which belonged to ApplicationFrameHost.exe, However, I got PID = 1936 correctly when calc's window is minimized.
This is due to the fact that "Calculator" is a tablet app and not a desktop app. Desktop apps give the right PID no matter if the window is minimized or not.
I think this SO post would be useful for you.
It seems that ApplicationFrameHost.exe is an app container that handle many child apps. An extra code is needed to retrieve the exact child app pid you are looking for.
base on that page, I wrote this piece of code and it worked for me, however, you might need to refine it.
typedef struct {
DWORD ownerpid;
DWORD childpid;
} windowinfo;
BOOL CALLBACK EnumChildWindowsCallback(HWND hWnd, LPARAM lp) {
windowinfo* info = (windowinfo*)lp;
DWORD pid = 0;
GetWindowThreadProcessId(hWnd, &pid);
if (pid != info->ownerpid) info->childpid = pid;
return TRUE;
}
void Show_PID()
{
Sleep(1000);
std::string window_name = "Calculator";
HWND hwnd = FindWindowA(NULL, window_name.c_str());
windowinfo info = { 0 };
GetWindowThreadProcessId(hwnd, &info.ownerpid);
info.childpid = info.ownerpid;
EnumChildWindows(hwnd, EnumChildWindowsCallback, (LPARAM)&info);
std::cout << "Process ID: " << info.childpid << std::endl;
}
int main()
{
for (int i = 0; i < 9; ++i)
{
Show_PID();
}
return 0;
}

you need check the returned hwnd value - you can view that when appcontainer app is suspended(you minimize it window) and when it active - you got different hwnd. for all app containers in active state - it main frame window belong not to it process but to ApplicationFrameHost.exe and have ApplicationFrameWindow class. but when it minimized - need click exactly on minimize button - process is suspended and.. however let run this code
if (HWND hwnd = FindWindowW(0, L"Alarms & Clock"))
{
ULONG pid, tid = GetWindowThreadProcessId(hwnd, &pid);
DbgPrint("%x %x.%x", hwnd, pid, tid);
WCHAR sz[MAX_PATH];
if (GetClassName(hwnd, sz, RTL_NUMBER_OF(sz)))
{
DbgPrint(" [%S]", sz);
}
if (HANDLE hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid))
{
PROCESS_EXTENDED_BASIC_INFORMATION pebi;
if (0 <= ZwQueryInformationProcess(hProcess, ProcessBasicInformation, &pebi, sizeof(pebi), 0))
{
DbgPrint(" Suspended=%x, flags(%x)", pebi.IsFrozen, pebi.Flags);
}
ULONG len = RTL_NUMBER_OF(sz);
if (QueryFullProcessImageNameW(hProcess, 0, sz, &len))
{
DbgPrint(" %S", sz);
}
CloseHandle(hProcess);
}
DbgPrint("\n");
}
and I got next output for 2 states:
1902e6 510.155c [Windows.UI.Core.CoreWindow] Suspended=1, flags(58) C:\Program Files\WindowsApps\Microsoft.WindowsAlarms_10.1605.1742.0_x64__8wekyb3d8bbwe\Time.exe
740414 574.934 [ApplicationFrameWindow] Suspended=0, flags(8) C:\Windows\System32\ApplicationFrameHost.exe

Related

Why doesn't my Windows API callback function run? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
I've written a code that terminates egui.exe. But my callback function doesn't run after the WM_CLOSE message is processed. Why?
#include <iostream>
#include <windows.h>
#include <psapi.h>
using namespace std;
HWND ESETWindow = 0; //Variable to store a handle to the main window
// of ESET Smart Security
HWND ConfirmationWindow = 0; //Variable to store a handle to the
// confirmation dialog box that appears
// when a WM_CLOSE message is sent to
// the ESET window.
DWORD EGUIPID = 0; //Variable to store the process identifier of egui.exe
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam);
VOID SendAsyncProc(HWND hwnd, UINT uMsg, ULONG_PTR dwData, LRESULT lResult);
int main()
{
cout << "Terminating ESET Smart Security..." << endl;
//Obtain an array of process identifiers including the PID of egui.exe
DWORD PIDs[1024]; //The array of process identifiers
DWORD bytesReturned;
if (!EnumProcesses(PIDs, sizeof(PIDs), &bytesReturned))
{
cerr << "Unable to enumerate the processes." << endl;
return 0;
}
//Enumerate the PIDs array to find the process of egui.exe.
DWORD nProcesses = bytesReturned / sizeof(DWORD);
for (DWORD i = 0;i < nProcesses;i++)
{
//Open the process to examine its executable file name.
HANDLE process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, PIDs[i]);
//Create a buffer for the name of the executable file.
PSTR processName = (PSTR) VirtualAlloc((LPVOID) NULL, (DWORD) 10, MEM_COMMIT, PAGE_READWRITE);
//Get the name of the executable file name.
GetModuleBaseName(process, NULL, processName, 10);
//Check if the executable file name is egui.exe.
if (!lstrcmpi(processName, TEXT("egui.exe")))
{
EGUIPID = PIDs[i];
break;
}
VirtualFree(processName, 0, MEM_RELEASE);
CloseHandle(process);
}
//Display an error message if the process identifier of egui.exe
//could not be found.
if (!EGUIPID)
{
cerr << "Unable to find process identifier of egui.exe" << endl;
return 0;
}
//Enumerate the top-level windows to find the main window of
// ESET Smart Security and store a handle to that window in the
// ESETWindow variable.
EnumWindows(EnumWindowsProc, 0);
//Display an error message if the window could not be found.
if (!ESETWindow)
{
cerr << "Unable to find the primary window of ESET Smart Security." << endl;
return 0;
}
//Send a WM_CLOSE message to the main window of egui.exe in order
// to display a confirmation dialog box.
if (!SendMessageCallback(ESETWindow, WM_CLOSE, 0, 0, SendAsyncProc, 0))
{
cerr << "Unable to send a WM_CLOSE message to the primary window of ESET Smart Security." << endl;
return 0;
}
//Wait a second for the confirmation dialog box to appear...
Sleep(1000);
//Enumerate the windows again to find the confirmation dialog box.
EnumWindows(EnumWindowsProc, 1);
//Display an error message if the confirmation dialog box
// could not be found.
if (!ConfirmationWindow)
{
cerr << "Unable to find confirmation message." << endl;
cout << "If you have ESET NOD32, it is probably terminated successfully.";
cin.get();
}
//Find the Yes button in the confirmation dialog box and display
// an error message if failed.
HWND button = FindWindowEx(ConfirmationWindow, NULL, NULL, TEXT("&Yes"));
if (!button)
{
cerr << "Unable to find Yes button in the message box." << endl;
return 0;
}
//Activate the confirmation dialog box and simulate a mouse click
// on the Yes button.
SetActiveWindow(ConfirmationWindow);
SendMessage(button, BM_CLICK, 0, 0);
cout << "ESET Smart Security was successfully terminated!";
//Keep the program running until the user presses Enter
// in the console window.
cin.get();
return 0;
}
//If lParam is 0, the function below finds the main window of
//ESET Smart Security, otherwise, it finds the confirmation
//dialog box.
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
//Check if hwnd belongs to a window of egui.exe.
DWORD PID = 0;
GetWindowThreadProcessId(hwnd, &PID);
if (PID != EGUIPID)
return TRUE; //Exit function and continue the enumeration.
//Check if the title of the window is "ESET Smart Security"
// or "ESET Node32 Antivirus".
int len = GetWindowTextLength(hwnd);
PSTR title = (PSTR) VirtualAlloc((LPVOID) NULL, (DWORD) (len + 1), MEM_COMMIT, PAGE_READWRITE);
GetWindowText(hwnd, title, (len + 1));
if ((lstrcmp(title, TEXT("ESET Smart Security"))) && (lstrcmp(title, TEXT("ESET NOD32 Antivirus"))))
return TRUE; //Exit function and continue the enumeration.
if (lParam)
{
//If lParam is nonzero and hwnd refers to the main
// window of egui.exe, exit function and continue
// the enumeration.
if (hwnd == ESETWindow)
return TRUE;
//Otherwise hwnd refers to the confirmation dialog box.
//So store it in the ConfirmationWindow variable.
ConfirmationWindow = hwnd;
return FALSE; //Exit function and stop the enumeration.
}
else
{
//hwnd refers to the main window of ESET Smart Security.
//So store it in the ESETWindow variable.
ESETWindow = hwnd;
return FALSE; //Exit function and stop the enumeration.
}
}
VOID SendAsyncProc(HWND hwnd, UINT uMsg, ULONG_PTR dwData, LRESULT lResult)
{
MessageBox(0, TEXT("ESET Smart Security was successfully terminated."), TEXT("Result"), MB_OK);
}
Although this program accomplishes its task perfectly, the callback function SendAsyncProc doesn't run after the WM_CLOSE message is processed and egui.exe is terminated. Could you tell me why?
The documentation for SendMessageCallback tells you, why your callback will not ever be called:
If the target window belongs to a different thread from the caller, then the callback function is called only when the thread that called SendMessageCallback also calls GetMessage, PeekMessage, or WaitMessage.
The target window obviously belongs to a different thread, because it runs in a different process. Your code doesn't perform any message retrieval. No callback.

Pasting data into any applications input field without simulating Ctrl+V. Windows c++

As my title states, I am trying to move data from a C++ application I am writing and input it into a field (specifically username and password fields) on any desktop application in windows. It needs to work for all applications.
Now I have already written a small program which copies data to the clipboard, and then simulates a Ctrl+V keyboard press to paste the data in. This however, feels like a terribly ugly way to do this. My question is, is there a better way?
Ps. From the research I have done everything seems to require that you modify the receiving application in some way. This option is unfortunately unavailable to me. So any solutions involving tweaking the receiving application won't be helpful.
Thank you for your help!
Sending keystrokes to another application is not a good solution. There are many potential problems, such as in C# sendkeys to other application to particular textfield. A better solution is to interface with the other program more directly. It requires a bit more technical understanding of how Windows works however. One of many advantages is that you can read text in the other application as easily as write it.
See my Clicking a Button in Another Application for a sample, but that is in C#. I hope the explanation at least is helpful. The same technique can be used to put data into a text box or text boxes then click a button. The WM_SETTEXT message would be used to put data into a textbox in another application. The following is a sample console program that puts text into Notepad.
#include "stdafx.h"
struct pidandhwnd {
DWORD dwProcessId;
HWND hwnd;
};
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
pidandhwnd *ppnh = (pidandhwnd *)lParam;
DWORD dwProcessId;
GetWindowThreadProcessId(hwnd, &dwProcessId);
if (ppnh->dwProcessId == dwProcessId)
{
ppnh->hwnd = hwnd;
return FALSE;
}
return TRUE;
}
int main()
{
TCHAR szCmdline[] = TEXT("Notepad.exe");
PROCESS_INFORMATION piProcInfo;
STARTUPINFO siStartInfo;
BOOL bSuccess = FALSE;
ZeroMemory(&piProcInfo, sizeof(PROCESS_INFORMATION));
ZeroMemory(&siStartInfo, sizeof(STARTUPINFO));
siStartInfo.cb = sizeof(STARTUPINFO);
siStartInfo.hStdError = NULL;
siStartInfo.hStdOutput = NULL;
siStartInfo.hStdInput = NULL;
LPARAM lParam = NULL;
pidandhwnd pnh;
const int ControlId = 15; // Edit control in Notepad
HWND hEditWnd;
bSuccess = CreateProcess(NULL,
szCmdline, // command line
NULL, // process security attributes
NULL, // primary thread security attributes
TRUE, // handles are inherited
0, // creation flags
NULL, // use parent's environment
NULL, // use parent's current directory
&siStartInfo, // STARTUPINFO pointer
&piProcInfo); // receives PROCESS_INFORMATION
if (!bSuccess) {
std::cout << "Process not started\n";
return 0;
}
std::cout << piProcInfo.dwProcessId << " Notepad Process Id\n";
WaitForInputIdle(piProcInfo.hProcess, 1000);
pnh.dwProcessId = piProcInfo.dwProcessId;
pnh.hwnd = NULL;
EnumDesktopWindows(NULL, EnumWindowsProc, (LPARAM)&pnh);
if (pnh.hwnd == NULL)
{
std::cout << "Notepad not found\n";
return 0;
}
//std::cout << "Notepad found\n";
// Get the edit box on Notepad
hEditWnd = GetDlgItem(pnh.hwnd, ControlId);
// Send the text
SendMessage(hEditWnd, WM_SETTEXT, NULL, (LPARAM)_T("This is from somewhere else."));
return 0;
}

How to find out if process created with ShellExecuteEx owns a window?

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

C++ - See if an hWnd window is responding or not?

I'm making an application to change some information around in another window.
The problem is, Sometimes it causes the window to "Not Respond."
So my question is, Using C++, How do I check to see if the window is still running or not?
I'm using this to look at my window:
HWND hWnds = FindWindow(0, WindowName);
if (hWnds <= 0) {
gameFound = false;
} else {
DWORD pId;
GetWindowThreadProcessId(hWnds, &pId);
hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pId);
if (!hProc) {
std::cout << "Failed.";
} else {
std::cout << "Window Found!";
Windows periodically sends out an event that asks if the program is alive, then it waits for it to respond. And if it doesn't respond within a certain amount of time it assumes it has crashed and says "not responding". So what you need to do is handle the window events.

C++/Win32 enumerate windows belonging to my process & close them

I have a Windows app that houses a web browser (Internet explorer) embedded in it. The app can be closed from another process by means of IPC. It works just fine except the situation when the embedded web browser may be displaying a pop-up dialog window (say, during saving of contents). In that case my app crashes when it tries to close from an outside request via IPC. (Internally it simply posts the WM_CLOSE message to itself.)
In light of that I thought to come up with a way to enumerate all windows that belong to my process and close them first before closing my process itself. The question is, how do you enumerate all windows belonging to my process for the purpose of closing them?
OK, I guess I got it myself. Here's if someone is interested:
#define SIZEOF(f) (sizeof(f) / sizeof(f[0]))
typedef struct _ENUM_POPUPS_INFO{
DWORD dwProcID;
HWND hThisWnd;
int nNextHWNDIndex;
HWND hFoundHWNDs[256];
}ENUM_POPUPS_INFO;
void CloseAllOpenPopups(HWND hWnd, int dwmsWait)
{
//'hWnd' = our main window handle (we won't close it)
//'dwmsWait' = maximum wait time in milliseconds, or -1 to wait for as long as needed
ENUM_POPUPS_INFO epi = {0};
BOOL bR;
int i, iIteration;
HWND hWndRoot, hWndActivePopup;
DWORD dwmsTickBegin = GetTickCount();
for(iIteration = 0;; iIteration = 1)
{
//Get our process ID
memset(&epi, 0, sizeof(epi));
epi.hThisWnd = hWnd;
epi.dwProcID = GetCurrentProcessId();
bR = EnumWindows(EnumPopupWindowsProc, (LPARAM)&epi);
//Did we get any
if(epi.nNextHWNDIndex == 0)
break;
//Wait on a second and later iteration
if(iIteration > 0)
{
if(dwmsWait != -1)
{
DWORD dwmsTick = GetTickCount();
int nmsDiff = abs((long)(dwmsTick - dwmsTickBegin));
if(nmsDiff >= dwmsWait)
{
//Timed out
break;
}
//Wait
Sleep(min(100, dwmsWait - nmsDiff));
}
else
{
//Wait
Sleep(100);
}
}
//Go through all windows found
for(i = 0; i < epi.nNextHWNDIndex; i++)
{
//Get root owner
hWndRoot = GetAncestor(epi.hFoundHWNDs[i], GA_ROOTOWNER);
if(!hWndRoot)
continue;
//Get it's active popup
hWndActivePopup = GetLastActivePopup(hWndRoot);
if(!hWndActivePopup)
continue;
//Close it
PostMessage(hWndActivePopup, WM_CLOSE, 0, 0);
}
}
}
BOOL CALLBACK EnumPopupWindowsProc(HWND hWnd, LPARAM lParam)
{
ENUM_POPUPS_INFO* pEPI = (ENUM_POPUPS_INFO*)lParam;
//Get process ID of the window
DWORD dwProcID = 0;
GetWindowThreadProcessId(hWnd, &dwProcID);
//We need this window only if it's our process
if(dwProcID == pEPI->dwProcID &&
pEPI->hThisWnd != hWnd &&
((GetWindowLongPtr(hWnd, GWL_STYLE) & (WS_VISIBLE | WS_POPUP | WS_CAPTION)) == (WS_VISIBLE | WS_POPUP | WS_CAPTION)))
{
if(pEPI->nNextHWNDIndex >= SIZEOF(pEPI->hFoundHWNDs))
{
//Stop, we're full
return FALSE;
}
//Add it
pEPI->hFoundHWNDs[pEPI->nNextHWNDIndex] = hWnd;
pEPI->nNextHWNDIndex++;
}
return TRUE;
}
When you want your process to exit, just call ExitProcess. It doesn't matter what windows might be open at the time, they all go away.