WinAPI访问其他应用程序的控件

时间:2011-03-08 16:37:32

标签: c++ winapi dll-injection

我需要从win计算器(calc.exe)获取所有控件的列表,并从我的应用程序中按下calc上的按钮。 我尝试了代码注入,现在可以从calc应用程序执行我的代码。在示例中,它发送msg框:

#define PROC_NAME _T("calc.exe")
#define MAX_READ 128
#include <windows.h>
#include <tlhelp32.h>

#pragma comment(linker,"/BASE:0x13140000") 

//-------- My code, which will be executed  from the app-------

DWORD WINAPI func(LPVOID)
{
    LoadLibrary(_T("kernel32.dll")); 
    LoadLibrary(_T("user32.dll"));
    MessageBox(0,_T("Hello from addres area of calculator"),_T("title"),0);
    return true;
}

//-------- find process ---------

DWORD GetProcessID(LPCWSTR lpNameProcess) 
{
    HANDLE snap;
    PROCESSENTRY32 pentry32;
    snap=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
    if(snap==INVALID_HANDLE_VALUE) return 0;
    pentry32.dwSize=sizeof(PROCESSENTRY32);
    if(!Process32First(snap,&pentry32)) {CloseHandle(snap);return 0;}
    do
    {
        if(!lstrcmpi(lpNameProcess,&pentry32.szExeFile[0]))
        {
            CloseHandle(snap);
            return pentry32.th32ProcessID;
        }
    }
    while(Process32Next(snap,&pentry32));
    CloseHandle(snap);
    return 0;
}

//-------- injection to another process -------------------

BOOL Inject(HANDLE hProc,DWORD(WINAPI* func)(LPVOID))
{
    DWORD id;
    DWORD ByteOfWriten;
    HMODULE hModule = GetModuleHandle(NULL);
    DWORD size=((PIMAGE_OPTIONAL_HEADER)((LPVOID)((BYTE*)(hModule)+((PIMAGE_DOS_HEADER)(hModule))->e_lfanew+sizeof(DWORD)+sizeof(IMAGE_FILE_HEADER))))->SizeOfImage;
    char* hNewModule = (char*)VirtualAllocEx(hProc,hModule,size,MEM_COMMIT|MEM_RESERVE,PAGE_EXECUTE_READWRITE);
    if(hNewModule==NULL) return false;
    WriteProcessMemory(hProc,hNewModule,hModule,size,&ByteOfWriten);
    if(ByteOfWriten!=size){return false;}
    HANDLE hThread=CreateRemoteThread(hProc,NULL,0,func,(LPVOID)hNewModule,0,&id);
    if(hThread==0) return false;
    return true;
}

int _tmain(int argc, _TCHAR* argv[])
{
    if(!Inject(OpenProcess(PROCESS_ALL_ACCESS,false,GetProcessID(PROC_NAME)),&func)) return false;
}

但是如何点击按钮并从calc上的某些控件获取文本?

我是如何尝试枚举子窗口的:

HWND hwnd, child;
    child = NULL;
    char buf[MAX_STR];          
    hwnd = getMyWnd();  // my own func, returns hwnd to main window 
    do 
    {
        //  here i tried to get child windows
        child = FindWindowExA(hwnd, child, NULL, NULL);
        GetWindowTextA( child, buf, MAX_STR - 1 );
        printf(buf); printf("\n");      
    } while (child != NULL);

2 个答案:

答案 0 :(得分:1)

我假设你已经获得了所需的按钮句柄

如果是这样尝试这个 - SendMessage(hButton,BN_CLICKED,0,0)我不记得常量,你可能需要查找它们。

更新以获取按钮窗口句柄 - 1.使用EnumChildWindows()枚举计算器的子窗口 http://msdn.microsoft.com/en-us/library/ms633494(VS.85).aspx

  1. 对于每个这样的窗口,通过使用GetWindowText检查其上的文本来查找它是否为按钮 http://msdn.microsoft.com/en-us/library/ms633520(VS.85).aspx

  2. 制作一个包含所有按钮手柄的数组,然后点击它们,就像你心中的内容一样:)

答案 1 :(得分:1)

查看MSDN上的MSAA和UIAutomation API - 它们旨在让一个应用程序在另一个应用程序中获取有关控件的信息,并且通常由自动化测试和可访问性工具和应用程序使用。

作为Windows SDK一部分的inspect.exe工具使用这些工具;并且您应该能够使用它来检查计算或各种其他应用程序中的按钮并与之交互。

Windows中的所有系统控件都支持这些API,许多其他应用程序也是如此(例如IE,Firefox);但它可能不适用于只是绘制自己的UI的第三方应用程序。