我正在尝试访问另一个应用程序中的ListView控件(位于Dialog中),并从控件中获取数据。这是我写的Win32代码(含有适当的评论):
HWND hListView32 = hRoot; //HANDLE to the ListView control within the Dialog, having class name - "SysListView32"
int cnt = (int) ::SendMessage(hListView32, LVM_GETITEMCOUNT, 0, 0L); //returns CORRECT item count of the ListView Control
int nItem=0,nRes;
for(int nItem=0;nItem<cnt;nItem++)
{
LVITEM LvItem; // ListView Item struct
char Text[255]={0};
char Temp[255]={0};
char Temp1[255]={0};
memset(&LvItem,0,sizeof(LvItem));
LvItem.mask=LVIF_TEXT;
LvItem.iSubItem=1; //Trying to get the 2nd Colomn text
LvItem.pszText=Text; //Does not returns any Text, after the below SendMessage is executed???
LvItem.cchTextMax=256;
LvItem.iItem=nItem;
nRes = (int)::SendMessage(hListView32,LVM_GETITEMTEXT, nItem, (LPARAM)&LvItem);
DWORD dd = ::GetLastError(); //returns 0
}
虽然代码正在执行,但我没有从控件中获取任何数据。但是,我能够从控件中检索正确的项目计数,但没有数据。
另一种方法可能是使用MSAA钩子来获取数据。但这将是一个非常漫长而繁琐的过程。这里没有想法。请帮助。
谢谢,
答案 0 :(得分:1)
有几种可能性。
DLL Injection
使用Windows挂钩。优点:简单直接。缺点:许多进程都会加载此dll。
DLL Injection
通过打开它进行调试来加载库,在此过程的上下文中使用VallocEx
分配虚拟内存的chunc,用WriteProcessMemory
写入内存并创建一个起始地址为LoadLibrary
的远程线程。优点:单个流程受到影响。缺点:比钩子解决方案复杂一点。
读取进程内存。与选项2相同,但不是编写此内存并远程执行代码,而是将消息LVM_GETITEMTEXT
发送到相关窗口,提供有效的已知内存位置,然后使用ReadProcessMemory
读取该位置。
答案 1 :(得分:1)
传递缓冲区的ListView消息仅在拥有ListView的进程的地址空间内工作。您必须使用VirtualAllocEx()
在同一进程中分配内存块,然后您可以使用WriteProcessMemory()
向其写入并根据需要填充ListView,然后您可以使用{{1并使用ReadProcessMemory()
解除分配。
试试这个(为简洁省略了错误处理):
VirtualFreeEx()
答案 2 :(得分:0)
我是由Remy Lebeau编写的代码,但在我的特殊情况下,它的工作非常奇怪。通过SendMessage(listview,LVM_GETITEMCOUNT,0,0)正确地检索元素数量 ,但循环每次都读取相同的元素!它不是第一个或最后一个元素,不是选中的,但似乎是随机的。这是我的代码:
HWND win=FindWindowEx(NULL, NULL, _("TEventLogView"), NULL);
HWND listview=FindWindowEx(win, NULL, _("TListView"), NULL);
int cnt = (int) ::SendMessage(listview, LVM_GETITEMCOUNT, 0, 0);
if (cnt > 0)
{
DWORD dwProcessId;
GetWindowThreadProcessId(listview, &dwProcessId);
int n = grdEvents->GetNumberRows();
HANDLE hProcess = OpenProcess(PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION, FALSE, dwProcessId);
LVITEM *pLvItem = (LVITEM*) VirtualAllocEx(hProcess, NULL, sizeof(LVITEM), MEM_COMMIT, PAGE_READWRITE);
LPTSTR pText = (LPTSTR) VirtualAllocEx(hProcess, NULL, sizeof(TCHAR)*255, MEM_COMMIT, PAGE_READWRITE);
for(int nItem = 0; nItem < cnt; ++nItem)
{
// need to read 1 - 3 subitems
for (int j = 1; j < 4; j++)
{
TCHAR Text[255] = {0};
LVITEM LvItem = {0};
LvItem.mask = LVIF_STATE | LVIF_TEXT;
LvItem.pszText = pText;
LvItem.cchTextMax = sizeof(TCHAR)*255;
LvItem.iItem = nItem;
LvItem.iSubItem = j;
int nRes1 = WriteProcessMemory(hProcess, pLvItem, &LvItem, sizeof(LVITEM), NULL);
int nRes2 = (int) ::SendMessage(listview, LVM_GETITEMTEXT, (WPARAM)nItem, (LPARAM)pLvItem);
if (nRes2 > 0)
{
ReadProcessMemory(hProcess, pText, &Text[0], sizeof(TCHAR)*nRes2, NULL);
// insert into wxWidgets grid
grdEvents->SetCellValue(nItem, j - 1, Text);
}
}
VirtualFreeEx(hProcess, pText, 0, MEM_RELEASE);
VirtualFreeEx(hProcess, pLvItem, 0, MEM_RELEASE);
CloseHandle(hProcess);
}
}