here is my code:
public static string ReadListViewItem(IntPtr lstview, int item) { const int dwBufferSize = 1024; int dwProcessID; LV_ITEM lvItem; string retval; bool bSuccess; IntPtr hProcess = IntPtr.Zero; IntPtr lpRemoteBuffer = IntPtr.Zero; IntPtr lpLocalBuffer = IntPtr.Zero; IntPtr threadId = IntPtr.Zero; try { lvItem = new LV_ITEM(); lpLocalBuffer = Marshal.AllocHGlobal(dwBufferSize); // Get the process id owning the window threadId = GetWindowThreadProcessId(lstview, out dwProcessID); if ((threadId == IntPtr.Zero) || (dwProcessID == 0)) throw new ArgumentException("hWnd"); // Open the process with all access hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, dwProcessID); if (hProcess == IntPtr.Zero) throw new ApplicationException("Failed to access process"); // Allocate a buffer in the remote process lpRemoteBuffer = VirtualAllocEx(hProcess, IntPtr.Zero, dwBufferSize, MEM_COMMIT, PAGE_READWRITE); if (lpRemoteBuffer == IntPtr.Zero) throw new SystemException("Failed to allocate memory in remote process"); // Fill in the LVITEM struct, this is in your own process // Set the pszText member to somewhere in the remote buffer, // For the example I used the address imediately following the LVITEM stuct lvItem.mask = LVIF_TEXT; lvItem.iItem = item; lvItem.iSubItem = 2; lvItem.pszText = (IntPtr)(lpRemoteBuffer.ToInt32() + Marshal.SizeOf(typeof(LV_ITEM))); lvItem.cchTextMax = 50; // Copy the local LVITEM to the remote buffer bSuccess = WriteProcessMemory(hProcess, lpRemoteBuffer, ref lvItem, Marshal.SizeOf(typeof(LV_ITEM)), IntPtr.Zero); if (!bSuccess) throw new SystemException("Failed to write to process memory"); // Send the message to the remote window with the address of the remote buffer SendMessage(lstview, LVM_GETITEMText, 0, lpRemoteBuffer); // Read the struct back from the remote process into local buffer bSuccess = ReadProcessMemory(hProcess, lpRemoteBuffer, lpLocalBuffer, dwBufferSize,IntPtr.Zero); if (!bSuccess) throw new SystemException("Failed to read from process memory"); // At this point the lpLocalBuffer contains the returned LV_ITEM structure // the next line extracts the text from the buffer into a managed string retval = Marshal.PtrToStringAnsi((IntPtr)(lpLocalBuffer + Marshal.SizeOf(typeof(LV_ITEM)))); } finally { if (lpLocalBuffer != IntPtr.Zero) Marshal.FreeHGlobal(lpLocalBuffer); if (lpRemoteBuffer != IntPtr.Zero) VirtualFreeEx(hProcess, lpRemoteBuffer, 0, MEM_RELEASE); if (hProcess != IntPtr.Zero) CloseHandle(hProcess); } return retval; }
no matter what i do, retval returns empty, although lpLocalBuffer does not.
here is the def from ListItem:
[StructLayout(LayoutKind.Sequential)] private struct LV_ITEM { public int mask; public int iItem; public int iSubItem; public int state; public int stateMask; public IntPtr pszText; public int cchTextMax; public int iImage; internal int lParam; internal int iIndent; }
I tried compiling for 86x, 64bit, any processor, nothing works at all!
any idea why this could be happening?
C # + .net4, windows 7 64bit.