Hello guys so here is my problem since i was stuck in this block of code for more then 2 day
i want to make my programe monitor a specifique application and wait for it to be lunch i tried the "Do and While loop" but its not working i have checked and rechecked and i couldnt find a solution for this problem
HWND hwnd = FindWindow(0,("my programme window name"));
do {
if(hwnd == nullptr ) { /* if the window has not beign found */
cout << "window not found!" << endl;
Sleep(1000);
system("cls");
}
}while(hwnd == nullptr);
/*******************************************************************/
starting the next code once the window of the programe has been found
so my problem is i keep getting ""window not found!" when i launch my own program first and then lunch the program wish i try to monitor , but when i start the program i wish to monitor then i launch my own program everything work fine
tnks for your help--- edit Problem sloved
You're not changing hwnd inside the loop. You need to call FindWindow() in the loop. You can use a regular while loop instead of do-while, so you don't need to do the call twice.
while ((hwnd = FindWindow(0, "my programme window name")) == nullptr) {
cout << "window not found!" << endl;
Sleep(1000);
system("cls");
}
First things first: Polling is wrong.
If you need to be informed that a certain window is created, use the tool that's specifically tailored for this. Set up a WinEvents hook (calling SetWinEventHook) that listens for EVENT_OBJECT_CREATE events. In your WinEventProc callback you can filter out the your window of interest, by inspecting it's window title, window class, certain styles (and combinations thereof).
This doesn't waste resources like your attempt to poll every second, and doesn't exhibit the race conditions either (e.g. missing a window because it was created and destroyed in between sampling points).
Assuming that the value of hwnd was nullptr when it entered the loop; you are not changing its value in the loop. Since the condition hwnd == nullptr is always true, you get an infinite loop.
In order to overcome this issue, you need to change the value of hwnd inside your loop.
Nothing in your loop changes hwnd, so it is impossible to get out of the loop (as you've seen).
You need to make something inside the loop change hwnd so that it is possible that (eventually) hwnd won't == nullptr. e.g. hwnd = FindWindow(0,("my programme window name"));
I'd refactor to:
HWND hwnd = FindWindow(0,("my programme window name"));
while(hwnd == nullptr)
{
cout << "window not found!" << endl;
Sleep(1000);
system("cls");
hwnd = FindWindow(0,("my programme window name"));
}
I think the problem is "FindWindow(0,("my programme window name"))" can't return an available hwnd so the loop is stuck.
Maybe you can try 10 times, if hwnd was still null, break the loop or exit the program.
#define MAX_COUNT 10
HWND hwnd = FindWindow(0,("my programme window name"));
int count = 0;
while(hwnd == nullptr && count < MAX_COUNT) {
count++;
cout << "window not found!" << endl;
Sleep(1000);
system("cls");
hwnd = FindWindow(0,("my programme window name"));
}
Related
Basically I created a simple Dll injection code with a basic Dll that shows a message box and my question is how can I now use the Dll file to make it write text into the Notepad while its running and it hasn't been saved/is temporary?
Is there a way to find a path to the file?
(i don't think so because its still writing into the ram and is untitled so doesn't have a save on any drives)
Or is there a stream i can write into?
Like Timo said in the comment, you can get the handle to the Notepad's Window, and then use it to write text into it, and it even wouldn't require from you to inject your DLL into the Notepad Process.
In Windows, every window is receiving messages from the Operating System (or from other programs, like what you're going to try out), those messages tell the window what action was made, for instance - Pressing down a key, or pressing a mouse button. That way, the program controlling the Window will know what kind of action it's supposed to do.
You can use the Spy++ Tool (spyxx.exe, comes builtin in every Visual Studio) to track what Windows does when you press a key down the keyboard into the Notepad's Window.
You can read further about the topic of window messages here:
https://learn.microsoft.com/en-us/windows/win32/learnwin32/window-messages
And working with Spy++ here:
https://learn.microsoft.com/en-us/visualstudio/debugger/introducing-spy-increment?view=vs-2019
Opening Spy++, we can see all the Windows in the our session, and we look for the Notepad's:
how it looks
Small POC I made for searching the appropriate Window, according to what found by Spy++ (forgive me for the globals, and make sure you are aware of what I did here):
HWND notepad_window;
HWND notepad_edit;
BOOL CALLBACK GetEditWindow(HWND hWnd, LPARAM lParam)
{
wchar_t window_text[MAX_PATH] = { 0 };
if (0 != GetClassNameW(hWnd, window_text, MAX_PATH))
{
std::wstring text(window_text);
if (std::wstring::npos != text.find(L"Edit"))
{
std::wcout << "Found it" << text << std::endl;
notepad_edit = hWnd;
return false;
}
}
return true;
}
BOOL CALLBACK GetNotepadWindow(HWND hWnd, LPARAM lParam)
{
wchar_t window_text[MAX_PATH] = { 0 };
// Fun fact - The GetWindowTextW also posts a window message to the window, the WM_GETTEXT message
if (0 != GetWindowTextW(hWnd, window_text, MAX_PATH))
{
std::wstring text(window_text);
if (std::wstring::npos != text.find(L"Notepad"))
{
std::wcout << "Found it" << text << std::endl;
notepad_window = hWnd;
return false;
}
}
return true;
}
int wmain()
{
EnumWindows(GetNotepadWindow, 0);
EnumChildWindows(notepad_window, GetEditWindow, 0);
}
After you have the HWND, you can start dealing with the message posting. You can use Spy++ again to 'tap' on the Notepad's Edit Window, and see every Window Message sent when pressing down a key, you will see the WM_KEYDOWN, followed by a WM_KEYUP most likely.
Then, you can use the PostMessage WinAPI function to post your own WM_KEYDOWN/KEYUP messages to the Notepad Window, hence controlling the input it gets.
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.
My approach to this problem turned out to be correct only in several programs. Why it isn't universal?
Works fine on:
Firefox
Visual Studio Text Editor
Unfortunately, in some cases nothing happens(even if I click into a textbox area before execution of my program):
Google Chrome
Notepad
GetLastError returns always 0, even using SendMessage instead of PostMessage.Could you point out my mistake?
#include <Windows.h>
#include <iostream>
int main()
{
HWND hCurrentWindow;
Sleep(5000);
hCurrentWindow = GetForegroundWindow();
std::cout<<"GO!!!\n";
for(int i=0; i<500; i++) //simulate 500 keystrokes of 'E'.
{
PostMessage(hCurrentWindow,WM_KEYDOWN,0x45,NULL);
PostMessage(hCurrentWindow,WM_KEYUP,0x45,NULL);
}
std::cout<<GetLastError()<<std::endl;
system("Pause");
return 0;
}
UPDATE after Maximus sugestion
#include <Windows.h>
#include <iostream>
int main()
{
HWND hCurrentWindow;
Sleep(5000);
hCurrentWindow = GetForegroundWindow();
if(!hCurrentWindow)
std::cout<<"Failed get set the window handle\n";
std::cout<<"GO!!!\n";
for(int i=0; i<500; i++)
{
PostMessage(hCurrentWindow,WM_KEYDOWN,0x45,0x45);
PostMessage(hCurrentWindow,WM_KEYUP,0x45,0x45);
}
std::cout<<GetLastError()<<std::endl;
system("Pause");
return 0;
}
There is no difference in effect.
UPDATE after Rob Kennedy's comment and Hans Passant's answer
#include <Windows.h>
#include <iostream>
int main()
{
HWND hCurrentWindow;
DWORD procID;
GUITHREADINFO currentWindowGuiThreadInfo;
Sleep(5000);
hCurrentWindow = GetForegroundWindow();
if(!hCurrentWindow)
std::cout<<"Failed get main the window handle\n";
GetWindowThreadProcessId(hCurrentWindow,&procID);
GetGUIThreadInfo(procID,¤tWindowGuiThreadInfo);
hCurrentWindow = currentWindowGuiThreadInfo.hwndFocus;
if(!hCurrentWindow)
std::cout<<"Failed get the child window handle\n";
std::cout<<"GO!!!\n";
for(int i=0; i<500; i++)
{
PostMessage(hCurrentWindow,WM_KEYDOWN,0x45, MapVirtualKey(0x45,MAPVK_VK_TO_VSC));
PostMessage(hCurrentWindow,WM_KEYUP,0x45, MapVirtualKey(0x45,MAPVK_VK_TO_VSC));
}
std::cout<<GetLastError()<<std::endl;
system("Pause");
return 0;
}
Now, "transparent" messages are sent every time. GetLastError() says:
ERROR_INVALID_WINDOW_HANDLE
1400 (0x578)
Invalid window handle.
GetLastError() "fixed"
int main()
{
HWND hCurrentWindow;
DWORD procID;
GUITHREADINFO currentWindowGuiThreadInfo;
Sleep(5000);
hCurrentWindow = GetForegroundWindow();
if(!hCurrentWindow)
std::cout<<"Failed get main the window handle\n";
GetWindowThreadProcessId(hCurrentWindow,&procID);
GetGUIThreadInfo(procID,¤tWindowGuiThreadInfo);
hCurrentWindow = currentWindowGuiThreadInfo.hwndFocus;
if(!hCurrentWindow)
std::cout<<"Failed get the child window handle\n";
std::cout<<"GO!!!\n";
for(int i=0; i<500; i++)
{
if(!PostMessage(hCurrentWindow,WM_KEYDOWN,0x45, MapVirtualKey(0x45,MAPVK_VK_TO_VSC))) std::cout<<GetLastError()<<std::endl;
if(!PostMessage(hCurrentWindow,WM_KEYUP,0x45, MapVirtualKey(0x45,MAPVK_VK_TO_VSC))) std::cout<<GetLastError()<<std::endl;
}
system("Pause");
return 0;
}
...outputs 1400 thousand times. Except this, nothing has changed.
This will of course happen when you post the message to the wrong window. Which is certainly the case for Notepad. It doesn't have just one window, something you can see with Spy++. GetForegroundWindow() returns you a top-level window, the frame window for Notepad. Inside of that frame window it has a child window, an EDIT control. That window needs to get the messages.
You'll need to jump through a few hoops to get that window, the GetFocus() function returns the window with the focus but that only works if you call it from the process that owns the window. When you do this out-of-process then you must first call GetWindowThreadProcessId() to get the ID of the thread that owns the foreground window. Then you must call GetGUIThreadInfo(), the GUITHREADINFO.hwndFocus it returns is the window handle you need.
This is still not without trouble, you cannot control the keyboard state of the process. In other words, the state of the Shift, Ctrl and Alt keys as well as any dead keys (like Alt+Gr on certain keyboard layouts). Favor sending WM_CHAR for typing keys.
Something else to bear in mind is that you can't always assume that the target application is handling user input in the same way. For example they could be using something GetAsyncKeyState() instead, causing your posted messages to have no effect at all.
You send lParam==NULL. It contains the scan code of the key which may be needed by the applications which aren't working currently.
Also, your code does not check the return value of GetForegroundWindow(). It may be NULL.
Lastly, you omit WM_CHAR, which is an important part of keyboard cycle.
Between sending the KeyDown and KeyUp you need any delay in some cases. I solved my similar situation by adding a pause of 100ms after KeyDown
{
PostMessage(hCurrentWindow,WM_KEYDOWN,0x45, MapVirtualKey(0x45,MAPVK_VK_TO_VSC));
Sleep(100);
PostMessage(hCurrentWindow,WM_KEYUP,0x45, MapVirtualKey(0x45,MAPVK_VK_TO_VSC));
}
How can I test if a button is being pressed ?
I am using EnumChildWindows() to enumerate the child windows of a given window, and one of the child window is a button, I want to test if that specific button is being pressed.
My code until know is:
BOOL CALLBACK MyEnumProc(HWND hwnd, LPARAM lParam)
{
char buffer[256];
GetWindowText(hwnd, buffer, sizeof(buffer));
cout << buffer << endl;
return true;
}
int main()
{
HWND hwnd = FindWindow(0, "Window to find");
EnumChildWindows(hwnd, MyEnumProc, 0);
return 0;
}
You can send the BM_GETSTATE message to the button control, if it is pressed the result will be
BST_PUSHED.
You need to inject a DLL into the process space, hook the window message loop (like you used to hand code a subclassed window in native Win32 API C code, Window Proc) (google-able) and listen to the actual messages.
All of this is ancient stuff for me, and I'm afraid that recent Windows versions (hopefully) made this a little bit more difficult to do.
That said, if you can get the application trusted with the right level of permissions, you should still be able to do this
I create a window without showing it:
int main()
{
CreateWindow("SysListView32","Geek",0, 0, 0, 0, 0,NULL, NULL, (HINSTANCE)GetCurrentProcess(), NULL);
getch();
}
...and in another process use FindWindow() to find its handle:
int main()
{
HWND H = FindWindow("SysListView32", "Geek");
std::cout<< "The handle of created window is : " <<H;
getch();
}
How is FindWindow finding its handle? I assumed it would not find it, because process1 is not showing the window.
How can I find only visible windows?
Even if a window is not visible, it is of course in the list of all existing windows that FindWindow enumerates (you can display this list using Spy++ for example). If you do not want to search for hidden windows, you have to check their flags:
HWND H = FindWindow("SysListView32", "Geek");
if (H) {
LONG style = GetWindowLong(H, GWL_STYLE);
if (style & WS_VISIBLE)
std::cout << "The handle of created visible window is : " << H << std::endl;
else
std::cout << "The handle of created hidden window is : " << H << std::endl;
} else {
std::cout << "No such window found" << std::endl;
}
FindWindow finds top-level windows.
While your CreateWindow call is creating a top-level window (i.e. one with no parent) I'm not convinced it will actually work.
It's certainly very unusual (if not wrong) to create a top-level SysListView32. ListView controls should be the children of top-level windows, not top-level windows in their own right.