Windows跨进程获取列表中的数据

首先需要用到Spy++来查看目标窗体信息

 主窗体Caption是"MFCApp"
 ListView class是"SysListView32"
 ListHeader  class是"SysHeader32"

下面是代码实现

复制代码
#include <iostream>
#include <string>
#include <Windows.h>
#include <CommCtrl.h>

using namespace std;

//回调函数用于枚举子控件
BOOL CALLBACK EnumChildProc(HWND hwndChild, LPARAM lParam) {
    char buffer[256] = { 0 };
    GetClassNameA(hwndChild, buffer, sizeof(buffer));
    std::string childClassName(buffer);
    std::cout << "Child Control Class Name: " << childClassName << std::endl;
    
    return TRUE;    
}

LPSTR ShunW2A(LPCWSTR lpcwszStrIn) {
    LPSTR pszOut = nullptr;
    if (lpcwszStrIn != nullptr) {
        int nInputStrLen = (int)wcslen(lpcwszStrIn);
        //获得缓冲所需的字节数大小        
        int nOutputStrLen = WideCharToMultiByte(CP_ACP, 0, lpcwszStrIn, nInputStrLen, nullptr, 0, 0, 0) + 2;
        pszOut = new char[nOutputStrLen];
        if (pszOut) {
            memset(pszOut, 0, nOutputStrLen);
            WideCharToMultiByte(CP_ACP, 0, lpcwszStrIn, nInputStrLen, pszOut, nOutputStrLen, 0, 0);
        }
    }
    return pszOut;
}

int main() {
    //获取目标应用程序的句柄
    HWND hWndParent = nullptr;
    hWndParent = FindWindowA(nullptr, "MFCApp");
    if (hWndParent == nullptr) {
        cout << L"未找到目标应用程序" << endl;

        return -1;
    }

    // 将目标窗口置顶
    SetWindowPos(hWndParent, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
    
    EnumChildWindows(hWndParent, EnumChildProc, 0);
    HWND hWndListCtrl = FindWindowExA(hWndParent, nullptr, "SysListView32", nullptr);
    if (hWndListCtrl == nullptr) {
        cout << "Child control not found with class name:" << "SysListView32" << endl;

        return -1;
    }
    DWORD PID;
    GetWindowThreadProcessId(hWndListCtrl, &PID);
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, PID);
    //获取目标进程句柄失败
    if (!hProcess) {
        cout << "获取目标句柄失败!" << endl;
        
        return -1;
    }
    
    int nBufferLength = 1024;
    //窗口句柄
    //HWND hWnd = NULL;
    //获取ListView列头句柄
    HWND hLVHeader = (HWND)::SendMessage(hWndListCtrl, LVM_GETHEADER, 0, 0);
    //获取ListView列数
    int nColumnCount = (int)::SendMessage(hLVHeader, HDM_GETITEMCOUNT, 0, 0);
    //获取ListView行数
    int nRowCount = (int)::SendMessage(hWndListCtrl, LVM_GETITEMCOUNT, 0, 0);
    if (nRowCount <= 0) {
        cout << "内容为空" << endl;

        return -1;
    }
    
    //在目标进程地址空间分配内存
    LVITEM *pVirtualItem = (LVITEM*)VirtualAllocEx(hProcess, NULL, sizeof(LVITEM), MEM_COMMIT, PAGE_READWRITE);
    wchar_t *pVirtualBuffer = (wchar_t*)VirtualAllocEx(hProcess, NULL, nBufferLength * 2, MEM_COMMIT, PAGE_READWRITE);
    if ((!pVirtualItem) || (!pVirtualBuffer)) {
        cout << "内存分配失败!" << endl;
        return -1;
    }

    int nColumnIndex = 0, nRowIndex = 0;
    //缓冲区大小    
    LVITEM lvitem;
    wchar_t* buffer = new wchar_t[nBufferLength];
    //UNICODE    
    wmemset(buffer, 0, nBufferLength);
    for (int i = 0; i < nRowCount; i++) {
        for (int j = 0; j < nColumnCount; j++)
        {
            nColumnIndex = i;
            nRowIndex = j;
            lvitem.cchTextMax = nBufferLength * 2;
            lvitem.iSubItem = nRowIndex;
            lvitem.pszText = pVirtualBuffer;
            //核心技术:将LVITEM结构体插入目标进程里,然后通过LVM_GETITEMTEXT消息获取指定项的文本            
            WriteProcessMemory(hProcess, pVirtualItem, &lvitem, sizeof(LVITEM), NULL);
            ::SendMessage(hWndListCtrl, LVM_GETITEMTEXT, (WPARAM)nColumnIndex, (LPARAM)pVirtualItem);
            ReadProcessMemory(hProcess, pVirtualBuffer, buffer, nBufferLength * 2, NULL);
            //转换成ANSI编码            
            char* ansiBuffer = ShunW2A(buffer);
            cout << ansiBuffer << endl;
            delete[]ansiBuffer;
        }
    }

    //释放目标进程里分配的内存    
    VirtualFreeEx(hProcess, pVirtualItem, sizeof(LVITEM), MEM_FREE);
    VirtualFreeEx(hProcess, pVirtualBuffer, nBufferLength * 2, MEM_FREE);
    CloseHandle(hProcess);
    delete[]buffer;

    // 将目标窗口的Z序位置设置为普通窗口
    SetWindowPos(hWndParent, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
    
    //获取按钮的文本内容
    HWND hWndButton = FindWindowExA(hWndParent, nullptr, "Button", nullptr);
    if (hWndButton == nullptr) {
        cout << "Child control not found with class name:" << "Button" << endl;

        return -1;
    }
    int textLength = GetWindowTextLengthA(hWndButton);
    if (textLength <= 0) {
        cout << "Control has no text" << endl;
        return -1;
    }    
    char* buffer_text = new char[textLength + 1];
    GetWindowTextA(hWndButton, buffer_text, textLength + 1);
    std::string controlText(buffer_text);
    delete[] buffer_text;
    cout << "Control Text:" << controlText << endl;

    return 1;
}
复制代码

测试App下载链接

posted @   TechNomad  阅读(163)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示