事件的缘由是要获取到Mt4客户端窗口的菜单绑定的ID号,使用spy++无果后,决定自己写程序实现。
方法一:
获取窗口HWND --> 获取主菜单 HMENU --> 获取子菜单 --> 获取菜单ID 失败告终。
方法二 就是本文的标题了。
直接在程序 SetWindowLong(mtClientWnd, GWL_WNDPROC, long(NewWndProc)); 发现会失败,就连 GetWindowLong()函数调用也是失败的。 于是提升进程权限,以管理员运行,结果都失败。
接下来就决定进一步提升权限了,把这代码让进程自己执行,那就没问题了吧。有代码注入和dll注入两种方式,dll注入比较简单我也比较熟悉,就用这一种吧。 dll注入成功却没有运行起来,发现Mt客户端是32位的,那么注入程序也只能是32位的,dll也只能是32位的。debug和release都可以, dll代码如下:
#include
WNDPROC mtClientWndFun;
LRESULT CALLBACK NewWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_COMMAND:
CString commandId;
commandId.Format("%d", wParam);
AfxMessageBox(commandId);
break;
}
//继续调用原来的窗口过程函数
return CallWindowProc(mtClientWndFun, hwnd, message, wParam, lParam);
}
BOOL CTestDllApp::InitInstance()
{
CWinApp::InitInstance();
HWND mtClientWnd = WndUtils::getWnd("DPSMarkets-test");
mtClientWndFun = (WNDPROC)GetWindowLong(mtClientWnd, GWL_WNDPROC);
if (mtClientWndFun == NULL)
{
AfxMessageBox("err");
}
else
{
AfxMessageBox("success");
}
SetWindowLong(mtClientWnd, GWL_WNDPROC, long(NewWndProc));
return TRUE;
}
注入程序代码:
HWND loginWnd = WndUtils::getWnd("DPSMarkets-test", true);
Process mtProcess(WndUtils::getWndProcessId(loginWnd));
mtProcess.injectionDll("E:\\project\\c++\\win32\\TestDll\\Release\\TestDll.dll");
--------------------------------------------------------------------------------------------------------
类库使用地址:https://github.com/huangshangbin/LibraryReconstruct
system/Process.hpp 有进程注入dll的接口。
使用Mt客户端点击菜单,就能弹出菜单ID了。
在其他程序通过 PostMessageA(a,WM_COMMAND,35429,0);就能调用响应的COMMAND ID绑定的消息函数了。
说明:
1 上面方式只能在32位上使用。64位
mtClientWndFun = (WNDPROC)GetWindowLong(mtClientWnd, GWL_WNDPROC);换成
mtClientWndFun = (WNDPROC)GetWindowLongPtr(mtClientWnd, GWLP_WNDPROC);
SetWindowLong(mtClientWnd, GWL_WNDPROC, long(NewWndProc));换成
SetWindowLongPtr(mtClientWnd, GWLP_WNDPROC, reinterpret_cast
64位的方式是通用的,未测试。
2 dll获取窗口的通用方法
HWND curWnd = NULL;
deque
for (auto wndInfo : wndInfoList)
if (WndUtils::getWndProcessId(wndInfo.m_hwnd) == ::GetCurrentProcessId())
{ curWnd = wndInfo.m_hwnd; break;}
3 找到需要注入的程序
deque
for (auto& wndInfo : wndInfoList)
{ Process wndProcess(WndUtils::getWndProcessId(wndInfo.m_hwnd));
if (StringUtils::isExistStringInString(wndProcess.getPath(), "firefox.exe")){
cout << wndInfo.m_text << endl;
cout << wndProcess.getPath() << endl;}}