2012-10-01 81 views
0

我试图访问ListView控件(位于一个对话框内)在另一个应用程序获取ListView控件的内容,并从控制中获取数据。下面是我写了Win32代码(与appropiate评论):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

'LVM_GETITEMTEXT'只能在同一个进程内工作。见例如大卫Heffernans评论[这太问题(http://stackoverflow.com/questions/4857411/listview-getitem-macro-lv-getitemtext-returns-empty-string-while-getting-ano)。 – user786653

回答

1

有几种可能性。

  1. DLL Injection使用windows挂钩。优点:简单直接。缺点:许多进程得到这个DLL加载。

  2. DLL Injection制定过程中打开它进行调试,在这个过程中的环境中使用VallocEx分配的虚拟内存chunc,写它的内存与WriteProcessMemory和创建与LoadLibrary功能的起始地址远程线程加载库。优点:单个进程受到影响。缺点:比钩子解决方案复杂一点。

  3. 读取进程内存。相同的选项2,但代替此写入存储器和远程执行的代码,发送消息LVM_GETITEMTEXT到窗口中的问题提供有效的已知的存储器位置,然后读该位置与ReadProcessMemory

+0

DLL注入不是* only *方法。也可以在目标应用程序中分配内存并让它处理'LVM_GETITEMTEXT'消息。 – user786653

+0

是的,你是对的。 – Serge

+0

@ user786653但是,只要你设法打开进程来分配和读取内存 - 加载DLL的一个步骤。 – Serge

1

传递缓冲区的ListView消息只能在拥有ListView的进程的地址空间内工作。你将不得不使用VirtualAllocEx()到同一个进程中分配的内存块,那么你可以写它与WriteProcessMemory()和具有ListView的填充需要,那么你就可以ReadProcessMemory()阅读并与VirtualFreeEx()释放它。

试试这个(略去了错误处理):

HWND hListView32 = hRoot; 

int cnt = (int) ::SendMessage(hListView32, LVM_GETITEMCOUNT, 0, 0); 
if (cnt > 0) 
{ 
    DWORD dwProcessId; 
    GetWindowThreadProcessId(hListView32, &dwProcessId); 

    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)*256, MEM_COMMIT, PAGE_READWRITE); 

    for(int nItem = 0; nItem < cnt; ++nItem) 
    { 
     TCHAR Text[256] = {0}; 

     LVITEM LvItem = {0}; 
     LvItem.mask = LVIF_TEXT; 
     LvItem.iSubItem = 1; 
     LvItem.pszText = pText; 
     LvItem.cchTextMax = 256; 
     LvItem.iItem = nItem; 

     WriteProcessMemory(hProcess, pLvItem, &LvItem, sizeof(LVITEM), NULL); 

     int nRes = (int) ::SendMessage(hListView32, LVM_GETITEMTEXT, nItem, (LPARAM)pLvItem); 
     if (nRes > 0) 
      ReadProcessMemory(hProcess, pText, &Text[0], sizeof(TCHAR)*nRes, NULL); 

     // use Text as needed... 
    } 

    VirtualFreeEx(hProcess, pText, 0, MEM_RELEASE); 
    VirtualFreeEx(hProcess, pLvItem, 0, MEM_RELEASE); 
    CloseHandle(hProcess); 
} 
0

我由雷米勒博copypasted代码,但它在我的特殊情况下的工作很奇怪。通过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); 
    } 
}