0

別のアプリケーションで (ダイアログ内にある) ListView コントロールにアクセスし、コントロール内からデータを取得しようとしています。私が書いている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
        }

コードは実行されていますが、コントロール内からデータを取得していません。ただし、コントロール内から正しいアイテム数を取得できますが、データは取得できません。

もう 1 つの方法は、MSAA フックを使用してデータを取得することです。しかし、それは非常に長く面倒なプロセスになります。ここでアイデアが不足しています。助けてください。

ありがとう、

4

3 に答える 3

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);
}
于 2012-10-02T00:49:29.017 に答える
1

いくつかの可能性があります。

  1. DLL InjectionWindows フックの使用。長所:シンプルでわかりやすい。短所: 多くのプロセスがこの dll をロードします。

  2. DLL Injectionライブラリをデバッグ用に開いてロードするプロセスを作成しVallocEx、このプロセスのコンテキストで使用して仮想メモリのチャンクを割り当て、そのメモリに書き込み、関数WriteProcessMemoryの開始アドレスでリモートスレッドを作成しLoadLibraryます。長所: 単一のプロセスが影響を受けます。短所: フック ソリューションよりも少し複雑です。

  3. プロセスメモリの読み取り。オプション 2 と同じですが、このメモリを書き込んでコードをリモートで実行する代わりにLVM_GETITEMTEXT、問題のウィンドウにメッセージを送信して有効な既知のメモリ位置を提供し、その位置を で読み取りますReadProcessMemory

于 2012-10-01T20:03:20.947 に答える