C++ Get Another Windows Hwnd In Same Process - c++

I've made a dll that you can inject into applications. I want that dll to find another window in the same process.
Here you can see a example. The console host (Konsolfönstervärd) is the dll I injected and I want that to find the lockdown-example window hwnd.
It is very simple to get the handle with the window title. But I don't want to hardcode it for just that application.
HWND parentHandle = FindWindowA(NULL, "Lockdown Example");
I have also tried some stuff with EnumWindows which basically prints all visible windows and their window title. And in the output of that you can see the "Lockdown Example" window.
10828: TheDll
388: Lockdown Example
13380: Microsoft Store
6664: Program Manager
How would I make it only do something when it found the "Lockdown Example" without just giving it a hardcoded title. Instead giving it something like GetCurrentProcessId()
static BOOL CALLBACK enumWindowCallback(HWND hWnd, LPARAM lparam) {
//GetWindowThreadProcessId();
int length = GetWindowTextLength(hWnd);
char* buffer = new char[length + 1];
GetWindowText(hWnd, buffer, length + 1);
std::string windowTitle(buffer);
// List visible windows with a non-empty title
if (IsWindowVisible(hWnd) && length != 0) {
cout << GetWindowThreadProcessId(hWnd, NULL) << ": " << windowTitle << endl;
}
return TRUE;
}
EnumWindows(enumWindowCallback, NULL)

So I came up to a answer with modifying the enumWindowCallback a little bit.
BOOL CALLBACK enumWindowCallback(HWND hwnd, LPARAM lParam)
{
int length = GetWindowTextLength(hwnd);
char* buffer = new char[length + 1];
GetWindowText(hwnd, buffer, length + 1);
std::string windowTitle(buffer);
DWORD lpdwProcessId;
GetWindowThreadProcessId(hwnd, &lpdwProcessId);
// 1. Checks if the current process is not equals to the value given in the lParam
// 2. Check if the current window is visible
// 3. Check if its not a empty name
// 4. Check so it is not the console window
// All these filters result in to only show all visible windows in the process
// Which in my case is "17260 | 15800: Lockdown Example"
if (lpdwProcessId == lParam && IsWindowVisible(hwnd) && length != 0
&& GetWindowThreadProcessId(GetConsoleWindow(), NULL) != GetWindowThreadProcessId(hwnd, NULL))
{
// Here you can do anything with the window handle (hwnd)
cout << lpdwProcessId << " | "<< GetWindowThreadProcessId(hwnd, NULL) << ": " << windowTitle << endl;
}
return TRUE;
}
Called it with:
EnumWindows(enumWindowCallback, GetCurrentProcessId()); // iterate over all windows

Related

How can I show a window with the a name given as parameter in Windows in C++

I would like to make my software usable for Linux and Windows (Linux already works). Now I still need some functions so I can run the software on Windows, too.
I am currently trying to use the EnumWindows() function to get the window names and then show the window in the foreground (which matches the parameter).
static BOOL CALLBACK setWindowFocus(HWND hWnd, LPARAM lparam) {
int length = GetWindowTextLength(hWnd);
char* buffer = new char[length + 1];
GetWindowText(hWnd, buffer, length + 1);
std::string windowTitle(buffer);
// List visible windows with a non-empty title
if (IsWindowVisible(hWnd) && length != 0) {
// Check if it is the right Windowshandle
if ( windowTitle.compare(programname) == 0 ) <-- programname is a static variable
{
// Set application to the foreground
SetForegroundWindow(hWnd);
}
}
return TRUE;
}
Additionally, I used this to create the variable:
std::string programname;
And this to call it:
static void setWindowFocus(std::string programname)
{
std::cout << "Setting focus to window." << std::endl;
tempsavedProgramname=programname;
EnumWindows(setWindowFocus, NULL);
}
That is working, as long as it is in main(). But, I would like to have it in an extra class with some other functions (I would like to remove the static variable too, if possible).
Is there a way I can use the EnumWindows() function with an anonymous function, or something?
Can I use something like this to pass a string to the function:
EnumWindows(setWindowFocus, reinterpret_cast<LPARAM>(stringvariable));
Or, are there other ways which I can try to reach my goal?
Includes which I used for the code:
Windows.h
winuser.h
string
iostream
I hope that I did not forgot one.
Yes, you can use the LPARAM to pass a string variable into your callback, eg:
static BOOL CALLBACK setWindowFocus(HWND hWnd, LPARAM lparam) {
std::string &programname = *reinterpret_cast<std::string*>(lparam);
int length = GetWindowTextLength(hWnd);
char* buffer = new char[length + 1];
GetWindowText(hWnd, buffer, length + 1);
std::string windowTitle(buffer);
delete[] buffer; // <-- ADD THIS!
/* I would use this instead:
int length = GetWindowTextLength(hWnd);
std::string windowTitle(length+1, '\0');
windowTitle.resize(GetWindowText(hWnd, &windowTitle[0], length + 1));
*/
// List visible windows with a non-empty title
if (IsWindowVisible(hWnd) && (length != 0)) {
// Check if it is the right Windowshandle
if (windowTitle == programname)
{
// Set application to the foreground
SetForegroundWindow(hWnd);
return FALSE;
}
}
return TRUE;
}
static void setWindowFocus(std::string programname)
{
std::cout << "Setting focus to window." << std::endl;
EnumWindows(setWindowFocus, reinterpret_cast<LPARAM>(&programname));
}
And yes, you can use a C++11 lambda for the callback, rather than a static class method, but only if you use a non-capturing lambda, which is implicitly convertible to a function pointer (capturing lambdas are not). Fortunately, the LPARAM makes that a possibility, eg:
static void setWindowFocus(std::string programname)
{
std::cout << "Setting focus to window." << std::endl;
EnumWindows(
[](HWND hWnd, LPARAM lparam) -> BOOL {
std::string &programname = *reinterpret_cast<std::string*>(lparam);
// ...
},
reinterpret_cast<LPARAM>(&programname)
);
}
Now, that being said, there is a much simpler solution - since you already know the exact window text you are looking for, you can use FindWindow() instead of EnumWindows(), eg:
static void setWindowFocus(std::string programname)
{
std::cout << "Setting focus to window." << std::endl;
HWND hWnd = FindWindowA(NULL, programname.c_str());
if (hWnd != NULL) {
// Set application to the foreground
SetForegroundWindow(hWnd);
}
}
Here's the callback wrapped up in a class
class enum_windows {
protected:
virtual BOOL call_back(HWND hwnd) {
// Your code here
return TRUE;
}
public:
void start() {
EnumWindows([](HWND hwnd, LPARAM lParam) -> BOOL {
enum_windows * obj = reinterpret_cast<enum_windows *>(lParam);
return obj->call_back(hwnd);
}, reinterpret_cast<LPARAM>(this));
}
};
(You've already accepted an answer - I'm a slow typer 😄). I'll leave this here anyway.

How to get the content of an edit box of another process in Windows?

Question:
In my program, I want to get the content of a specific edit box (or input box, text box...) of another process. For example, when the cursor is in the first column, "TextBox1" should be returned.
What I have tried
Use GetDlgItem and GetWindowText
Send WM_GETTEXT message to the window, which was suggested in a Q&A in from the august 2001 issue of MSDN Magazine and a stackoverflow question
char currentContext[256];
SendMessage(cfg.mainWnd,
WM_GETTEXT, sizeof(currentContext) / sizeof(currentContext[0]), (LPARAM)currentContext);
// cfg.mainWnd is the window which edit boxes lie in.
EnumChildWindows and callback
HWND GetInputWindow()
{
HWND activeWindow = GetForegroundWindow();
// lpdwProcessId cannot be null...
DWORD a = 1;
LPDWORD lpdwProcessId = &a;
auto threadId = GetWindowThreadProcessId(activeWindow, lpdwProcessId);
std::cout << "ThreadId: " << threadId << " ProcessId: " << *lpdwProcessId << "\n";
return activeWindow;
}
BOOL CALLBACK EnumChildProc(HWND hWnd, LPARAM lParam)
{
std::cout << "Being called.\n";
char temp1[256];
char temp2[256];
GetClassNameA(hWnd, temp1, 255);
if (!strcmp(temp1, "Edit"))
{
SendMessage(hWnd, WM_GETTEXT, sizeof(temp2) / sizeof(char), (LPARAM)temp2);
return false;
}
printf("text: %s", temp2);
MessageBox(NULL, temp2, L"test", MB_OK);
return true;
}
// ...
HWND activeWindow = GetInputWindow();
EnumChildWindows(activeWindow, EnumChildProc, 0);
All the methods above just get "MainWindow", i.e. the title of the window in the example above.
Appendix
I used spy++ to monitor the window in the example. Just one window was catched.

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.

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

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

Getting a list of all open windows in c++ and storing them

I'm currently trying to get a list of all opened windows and storing them inside a vector. I've been looking at the code so much that the solution could be very easy but I don't seem to get it done without a global variable (which I want to avoid).
Here is the code:
#include "stdafx.h"
#include "json.h"
#include <algorithm>
using namespace std;
vector<string> vec;
BOOL CALLBACK speichereFenster(HWND hwnd, LPARAM substring){
const DWORD TITLE_SIZE = 1024;
TCHAR windowTitle[TITLE_SIZE];
GetWindowText(hwnd, windowTitle, TITLE_SIZE);
int length = ::GetWindowTextLength(hwnd);
wstring temp(&windowTitle[0]);
string title(temp.begin(), temp.end());
if (!IsWindowVisible(hwnd) || length == 0 || title == "Program Manager") {
return TRUE;
}
vec.push_back(title);
return TRUE;
}
int main() {
EnumWindows(speichereFenster, NULL);
cin.get();
return 0;
}
I want to store all titles in the vector but I don't know how as I can't pass the vector into the function...
Thanks!!!
The second parameter (lParam) to EnumWindows is documented as:
An application-defined value to be passed to the callback function.
Just pass your container to the API call:
int main() {
std::vector<std::wstring> titles;
EnumWindows(speichereFenster, reinterpret_cast<LPARAM>(&titles));
// At this point, titles if fully populated and could be displayed, e.g.:
for ( const auto& title : titles )
std::wcout << L"Title: " << title << std::endl;
cin.get();
return 0;
}
And use it in your callback:
BOOL CALLBACK speichereFenster(HWND hwnd, LPARAM lParam){
const DWORD TITLE_SIZE = 1024;
WCHAR windowTitle[TITLE_SIZE];
GetWindowTextW(hwnd, windowTitle, TITLE_SIZE);
int length = ::GetWindowTextLength(hwnd);
wstring title(&windowTitle[0]);
if (!IsWindowVisible(hwnd) || length == 0 || title == L"Program Manager") {
return TRUE;
}
// Retrieve the pointer passed into this callback, and re-'type' it.
// The only way for a C API to pass arbitrary data is by means of a void*.
std::vector<std::wstring>& titles =
*reinterpret_cast<std::vector<std::wstring>*>(lParam);
titles.push_back(title);
return TRUE;
}
Notes:
The code presented uses a std::wstring in place of std::string. This is necessary so that the entire character set can be represented.
As written, the code isn't correct. There are (invisible) code paths, that have no well-defined meaning. The Windows API is strictly exposed as a C interface. As such, it doesn't understand C++ exceptions. Particularly with callbacks it is vital to never let C++ exceptions travel across unknown stack frames. To fix the code apply the following changes:
[C++11 only] Mark the callback noexcept.
Wrap the entire callback inside a try-catch block, and handle any exceptions appropriately.
[C++11 only] With C++11 you can pass C++ exceptions across unknown stack frames, by passing a std::exception_ptr, and calling std::rethrow_exception at the call site.
Simple code to get all visible windows with non empty title
for (HWND hwnd = GetTopWindow(NULL); hwnd != NULL; hwnd = GetNextWindow(hwnd, GW_HWNDNEXT))
{
if (!IsWindowVisible(hwnd))
continue;
int length = GetWindowTextLength(hwnd);
if (length == 0)
continue;
char* title = new char[length+1];
GetWindowText(hwnd, title, length+1);
if (title == "Program Manager")
continue;
std::cout << "HWND: " << hwnd << " Title: " << title << std::endl;
}