Read Items from a ListView in another Process

I have a windows application that controls another windows application.  I need to read the items in a SysListView32 control in the app being controlled.  I have the handle to the control and can call the ListView_SetItemCount and ListView_EnsureVisible macros OK with the correct results.  I can not get ListView_GetItemText to work though.  I think it may be because of pointers across different processes but I noticed LB_GETTEXT works with a ListBox control?  Is there a way to read from a ListView in a different process?

Who is Participating?
NickRepinConnect With a Mentor Commented:
3 ways possible:

1)If B is written by you, send WM_COPYDATA message with the item text to B. When B receives this message, it must get LV item itself.

2)Install hook (SetWindowHookEx, for example WH_GETMESSAGE) on the LV thread (use GetWindowThreadProcessId). You must get an item from the hook proc (which is in the hook dll). It'll work because hook proc is in the address space of B.

3) No documented way for 95/98.
For NT:
Alloc memory in the B address space using pMem=VirtualAllocEx()
Place LV_ITEM inside pMem using WriteProcessMemory.
Then call ListView_InsertItem(lv, pMem). Then use ReadProcessMemory to get result.

Sorry, I copied this text from my  previous answer to the same question. That question was about inserting an item into a list view. So may be my answer above is not clear enough.

If another app is written by you, it's better to use WM_COPY message.

If another app is not yours, then you have to use the one of the Windows hooks to get access to the address space of another process (you have to place the hook into DLL).

If your program will work on NT (or Win2000) only, then VirtualAllocEx is the best solution.

Choose one of the ways above and I'll give you additional details if necessary.
joeslowAuthor Commented:
I did not write the app I am trying to control, nor do I have the source code to modify it...
Get your problem seen by more experts

Be seen. Boost your question’s priority for more expert views and faster solutions

joeslowAuthor Commented:
Also, my app will only be running on NT.  I need a solution where I don't need to modify the app I am trying to control (B).

Thank you,
Ok, you know the window handle of the listview in B (hLV).

1) Obtain process id of B by GetWindowThreadProcessId(hLV,&pid)

2) Get the process handle of B by OpenProcess(PROCESS_VM_WRITE| PROCESS_VM_OPERATION | PROCESS_VM_READ)

3) Allocate the memory in the address space of B by VirtualAllocEx. Allocated block must be large enough to hold LVITEM structure and the buffer for the item text. Like this:

 struct S {
    LVITEM it;
    char buf[120];
 } s;

 S* ps=VirtualAllocEx(... sizeof(s)...)

4) Fill allocated memory by WriteProcessMemory:;
     LPBYTE(ps)+(LPBYTE(s.buf)-LPBYTE(&s))  );

Now copy s struct to ps by WriteProcessMemory.

5) Call ListView_GetItem(hLV,ps);

6) Read contents of ps->buf by ReadProcessMemory()

7) Use VirtualFreeEx to free memory and CloseHandle to close process handle.
joeslowAuthor Commented:
Thanks for the detailed explanation, I would have never figured this out in time.
All Courses

From novice to tech pro — start learning today.