I'm trying to use WindowFromPoint() to retrieve the handle of a button and then use SendMessage() to click the button.
I don't get an error with my code but the button isn't getting clicked either..
Basically nothing happens.
I have already confirmed that the coordinates point directly to the location of the button.
I have also tried ChildWindowFromPoint() but it didn't change anything.
Here is my code:
std::cout << "Assigning parent Window..." << std::endl;
for (std::list<Window>::iterator i = mainDetector.getWindowList().begin(); i != mainDetector.getWindowList().end(); ++i)
{
if (i->getTitle().find(windowTitle) != std::string::npos)
{
parentWindowHandle = (HWND)i->getHandle();
std::cout << "Parent Window assigned." << std::endl;
break;
}
}
std::cout << "Clicking button..." << std::endl;
buttonHandle = ChildWindowFromPoint(parentWindowHandle, registerButtonLoc);
SendMessage(buttonHandle, WM_LBUTTONDOWN, NULL, NULL);
SendMessage(buttonHandle, WM_LBUTTONUP, NULL, NULL);
Hope someone tell me where my mistake is..
Related
here is code.
char* getURL() {
char* urlstr;
if FAILED(CoInitialize(nullptr))
cout << "something error..." << endl;
struct coinit { ~coinit() { CoUninitialize(); } } cleanup;
//find the first visible window in firefox
HWND hwnd = NULL;
while (true)
{
hwnd = FindWindowEx(0, hwnd, (LPCSTR)"MozillaWindowClass", NULL);
if (!hwnd)
return 0;
if (IsWindowVisible(hwnd))
break;
}
//initialize UIAutomation
CComPtr<IUIAutomation> uia;
if FAILED(uia.CoCreateInstance(CLSID_CUIAutomation))
cout << "something error." << endl;
CComPtr<IUIAutomationElement> root, navigation, editbox;
CComPtr<IUIAutomationCondition> c1, c2;
//find root from hwnd handle
if FAILED(uia->ElementFromHandle(hwnd, &root))
cout << "something error." << endl;
//find navigation bar as child of root
uia->CreatePropertyCondition(UIA_AutomationIdPropertyId,
CComVariant(L"nav-bar"), &c1);
if FAILED(root->FindFirst(TreeScope_Children, c1, &navigation))
cout << "something error." << endl;
//find editbox under as descendant of navigation
uia->CreatePropertyCondition(UIA_AutomationIdPropertyId,
CComVariant(L"urlbar-input"), &c2);
if FAILED(navigation->FindFirst(TreeScope_Descendants, c2, &editbox))
cout << "something error." << endl;
//get the string in editbox
CComVariant url;
if FAILED(editbox->GetCurrentPropertyValue(UIA_ValueValuePropertyId, &url))
cout << "something error." << endl;
//if (url.bstrVal) {
// wprintf(L"[%s]\n", url.bstrVal);
//}
if (url.bstrVal == NULL) urlstr = (char*)"None";
else urlstr = _com_util::ConvertBSTRToString(url.bstrVal);
return urlstr;
i wanna get url from firefox tab.
I tried __try, but Cannot use __try in functions that require object unwinding.
I do not know where the error is coming from.
Can anyone tell me how I can prevent this error?
environments: Windows11, Visual Studio 2019
When I changed the library to not throw exceptions, I found that I was getting an error here.
if FAILED(navigation->FindFirst(TreeScope_Descendants, c2, &editbox))
This debugging error might happen when you pass a smart pointer (CComPtr) to COM like so:
CComPtr<IUIAutomationElement> root, navigation, editbox;
CComPtr<IUIAutomationCondition> c1, c2;
// Find root from hwnd handle
if (FAILED(uia->ElementFromHandle(hwnd, &root))) // Here, we pass an IUIAutomationElement as input.
cout << "Something Error." << endl;
When you pass a CComPtr as an input, you must release that smart pointer before using it again like so:
root.Release();
Not only for that smart pointer, but for any smart pointer you pass as an input you should release it before using again.
See this MSDN link: Debug Assertion Error when debugging CComPtr
Learn more about CComPtr and smart pointers here: COM Coding Practices
I'm Korean student.
Now this is my first question after signing up.
DWORD getProcessId() {
PROCESSENTRY32 process_infor;
process_infor.dwSize = sizeof(PROCESSENTRY32);
HANDLE snap_handle = CreateToolhelp32Snapshot(
TH32CS_SNAPALL, //스냅 단계
NULL //스냅할 pid
);
if (snap_handle != INVALID_HANDLE_VALUE) {
Process32First(snap_handle, &process_infor);
do {
wchar_t* temp = process_infor.szExeFile;
wstring ws(temp);
string name(ws.begin(), ws.end());
if (name == "notepad.exe") {
cout << name << " : " << process_infor.th32ProcessID << endl;
return process_infor.th32ProcessID;
}
} while (Process32Next(snap_handle, &process_infor));
}
CloseHandle(snap_handle);
return FALSE;
}
BOOL inject() {
HMODULE dll_handle;
HOOKPROC func;
HHOOK process_hook;
dll_handle = LoadLibrary(L"hello.dll");
func = (HOOKPROC) GetProcAddress(dll_handle, "injectSuccess");
cout << "handle : " << dll_handle << endl;
cout << "pid : " << getProcessId() << endl;
process_hook = SetWindowsHookEx(
WH_KEYBOARD,
func,
dll_handle,
getProcessId()
);
cout << "pook : " << process_hook << endl;
cout << "err : " << GetLastError() << endl;
FreeLibrary(dll_handle);
return FALSE;
}
There seems to be a problem with SetWindowsHookEx of the inject function in this case. The dll file loads well, and the injectSuccess function inside is well fetched. (I tried running it, but it worked)
And I wondered if the argument values of SetWindowsHookEx were entered incorrectly, so I compared them and checked them continuously, but I couldn't find any difference. So, I tried GetLastError() with the return value of SetWindowsHookEx below, but the return value is 0 and the error code is 87 ("the parameter is incorrect").
So I searched, but I can't speak English well and I'm a beginner, so I'm not sure.
According to the SetWindowsHookExW:
dwThreadId
A handle to the DLL containing the hook procedure pointed to by the lpfn parameter. The hMod parameter must be set to NULL if the dwThreadId parameter specifies a thread created by the current process and if the hook procedure is within the code associated with the current process.
So what SetWindowsHookExW needs is the thread ID, and you pass in the process ID of notepad.exe, so the parameter is wrong.
I creat a sample and test the following code:
BOOL inject() {
HMODULE dll_handle;
HOOKPROC func;
HHOOK process_hook;
dll_handle = LoadLibrary(L"hello.dll");
if (dll_handle) func = (HOOKPROC)GetProcAddress(dll_handle, "injectSuccess");
else return FALSE;
cout << "handle : " << dll_handle << endl;
cout << "pid : " << getProcessId() << endl;
HWND h = FindWindow(L"notepad", NULL);
DWORD pid;
threadID = GetWindowThreadProcessId(h, NULL);
cout << "threadID = " << threadID << endl;
process_hook = SetWindowsHookEx(
WH_KEYBOARD,
func,
dll_handle,
threadID
);
cout << "pook : " << process_hook << endl;
cout << "err : " << GetLastError() << endl;
if(dll_handle) FreeLibrary(dll_handle);
return FALSE;
}
This example worked for me, and you can see the difference between pid and threadID:
Edit
According to the document:
An application installs the hook procedure by specifying the
WH_KEYBOARD hook type and a pointer to the hook procedure in a call to
the SetWindowsHookEx function. This hook may be called in the context
of the thread that installed it. The call is made by sending a message
to the thread that installed the hook. Therefore, the thread that
installed the hook must have a message loop. So if you want to run
this func, you need to add a message loop.
You can refer to the following code:
int main()
{
inject();
MSG msg;
while (GetMessageW(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
}
When you press the button, the message box will pop up:
Because there are two messages for each key press and release, func is triggered twice each time.If you only want to trigger every time a button is pressed, you can modify the following code:
if ((0x80000000 & lParam) == 0)//This means that when the key is pressed
{
MessageBox(NULL, L"Success (dll injection)", L"Window", MB_OK);
}
You can refer to KeyboardProc to view the messages for each value in lParam.
When I debug the pcl documentation visualization mouse event function code as following shows:
viewer->registerMouseCallback(mouseEventOccurred, (void*)&viewer);
void mouseEventOccurred(const pcl::visualization::MouseEvent &event,void* viewer_void)
{
boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer = *static_cast<boost::shared_ptr<pcl::visualization::PCLVisualizer> *> (viewer_void);
if (event.getButton() == pcl::visualization::MouseEvent::LeftButton &&
event.getType() == pcl::visualization::MouseEvent::MouseButtonRelease)
{
std::cout << "Left mouse button released at position (" << event.getX() << ", " << event.getY() << ")" << std::endl;
char str[512];
sprintf(str, "text#%03d", text_id++);
viewer->addText("clicked here", event.getX(), event.getY(), str);
}
}
If I remove the code:
viewer->addText("clicked here", event.getX(), event.getY(), str);
It would work well, or I encountered an error:
I do not know how to solve this problem. Thanks!
After I clicked the Retry, the exception shows as:
Exception
What is the difference between the output of event.window.windowID and SDL_GetWindowID()?
Why is it that std::cout << m_SDLEvent.window.windowID << std::endl;
outputs 1819558491 in console while std::cout << SDL_GetWindowID(m_SDLWindow) << std::endl; outputs 1 ?
How would I achieve getting the right ID of my SDL_Window* in the method below?
void InputManager::Update()
{
SDL_PollEvent(&m_SDLEvent);
switch (m_SDLEvent.type)
{
case SDL_QUIT:
std::cout << m_SDLEvent.window.windowID << std::endl;
SDL_HideWindow(SDL_GetWindowFromID(m_SDLEvent.window.windowID));
break;
}
}
You're seeing garbage window ID because you access an inactive union field. That's undefined behavior.
You can only access m_SDLEvent.window if m_SDLEvent.type == SDL_WINDOWEVENT.
But if m_SDLEvent.type == SDL_QUIT, you have to use m_SDLEvent.quit structure, which has no field for window id (because SDL_QUIT is not specific to a window, but means that the entire application should be closed).
Okay so HolyBlackCat's answer brought me to the right direction.
Instead of using SDL_QUIT (which is the quit event for the entire app, not one window) I should've checked for SDL_WINDOWEVENT_CLOSE which is an SDL_WINDOWEVENT which can be received by m_SDLEvent.window.event instead of m_SDLEvent.type
So the code now looks like this:
void InputManager::Update()
{
SDL_PollEvent(&m_SDLEvent);
if (m_SDLEvent.type == SDL_WINDOWEVENT)
{
switch (m_SDLEvent.window.event)
{
case SDL_WINDOWEVENT_CLOSE:
std::cout << m_SDLEvent.window.windowID << std::endl;
SDL_HideWindow(SDL_GetWindowFromID(m_SDLEvent.window.windowID));
break;
}
}
}
Now std::cout << m_SDLEvent.window.windowID << std::endl; outputs the correct ID.
In efforts to learn more C++, I have chosen - you know - something fun to do and that is writing to random application's memory. The code I have written seems to work on all applications but I am having difficulties getting it to work with Google Chrome tabs.
What I am trying to do is simply change my score on Slope (on y8.com) for which I have the memory address with the help of cheat engine. The problem seems to be retrieving the Process ID of the tab. Using Chrome's Task Manager, I translated the tab's address to hex, opened the process in cheat engine and found the score address.
Here the problem comes. Whenever I use GetWindowThreadProcessId(window, &processID); cout << processID, it doesn't print the ID which can be seen in chrome's task manager for the game's tab. In fact, it prints the ID of chrome as a whole (which I know because in chrome's task manager, "chrome" has that ID). And the score cannot be written to or read from chrome's processID. If I ignore this problem, buffer seems to always print as 0.. no changes.
I am very new to this, and expect myself not to know what I am talking about. If you test the game yourself, you'll have to find the address that your chrome is using at the time. But here's the code (I have commented out the WriteProcessMemory and put Read just so I get it working before I write anything):
#include <iostream>
#include <string>
#include <Windows.h>
using namespace std;
int main() {
int buffer = 0;
LPVOID address = (LPVOID)0x15E7E1B0FB8/*(0x000000000192DFA0 + 0x0000291D8FE04000 + 0x18)*/;
cout << "Begin playing the game and wait for the 0 score to appear" << endl;
HWND window = FindWindow(NULL, "Slope Game - Play online at Y8.com");
if (window) {
cout << "Game found running! You ready to hax?" << endl;
DWORD processID = 11180;
GetWindowThreadProcessId(window, &processID);
HANDLE handle = OpenProcess(PROCESS_ALL_ACCESS, false, processID);
if (handle) {
/*string hackedScoreInput = "0";
cout << "Desired Score: " << flush; getline(cin, hackedScoreInput);
int hackedScore = stoi(hackedScoreInput);
int suc = WriteProcessMemory(handle, address, &hackedScore, sizeof(hackedScore), NULL);
if (suc > 0) {
cout << "HAXED!" << endl;
CloseHandle(handle);
}
else {
cerr << GetLastError() << endl;
cerr << hackedScore << " of size: " << sizeof(hackedScore) << endl;
return 3;
}*/
while (true) {
ReadProcessMemory(handle, address, &buffer, sizeof(buffer), NULL);
cout << buffer << " at adress: " << processID << endl;
Sleep(100);
system("CLS");
}
}
else {
cerr << "Could not open the process" << endl;
return 2;
}
}
else {
cerr << "Error! Could not find window!" << endl;
Sleep(3000);
return 1;
}
return 0;
}
What's wrong with the code?
Modern browsers use multiple processes and there is no rule that says that a browser tab HWND has to be owned by the process where the web page "runs".
Some browser implementations might have one main process that hosts the UI including all tabs but the actual web page content might be rendered to a shared bitmap/memory in a different process where it is safe to run scripts etc.
Chrome is open source so you could take a look and see if there is a way to find out which render process renders a certain tab by looking at the child processes command line arguments.