/// <summary> /// Returns the text for a specific item /// </summary> /// <param name="hWnd"></param> /// <param name="text"></param> /// <returns></returns> public string GetItemText(int itemHwnd) { const int dwBufferSize = 1024; int dwProcessID; Win32.TVITEM tvItem; string retval; bool bSuccess; IntPtr hProcess = IntPtr.Zero; IntPtr lpRemoteBuffer = IntPtr.Zero; IntPtr lpLocalBuffer = IntPtr.Zero; IntPtr threadId = IntPtr.Zero; try { tvItem = new Win32.TVITEM(); // Allocate a buffer in the local process lpLocalBuffer = Marshal.AllocHGlobal(dwBufferSize); // Get the process id owning the treeview threadId = Win32.GetWindowThreadProcessId(handle, out dwProcessID); if((threadId == IntPtr.Zero) || (dwProcessID == 0)) throw new ArgumentException("Could not found thread process id"); // Open the process with all access hProcess = Win32.OpenProcess(Win32.PROCESS_ALL_ACCESS, false, dwProcessID); if(hProcess == IntPtr.Zero) throw new ApplicationException("Failed to access process"); // Allocate a buffer in the remote process lpRemoteBuffer = Win32.VirtualAllocEx(hProcess, IntPtr.Zero, dwBufferSize, Win32.MEM_COMMIT, Win32.PAGE_READWRITE); if(lpRemoteBuffer == IntPtr.Zero) throw new SystemException("Failed to allocate memory in remote process"); // Fill in the TVITEM struct, this is in your own process // Set the pszText member to somewhere in the remote buffer, // In this case we use the address imediately following the TVITEM stuct tvItem.mask = ((int)Win32.TVIF.TEXT | (int)Win32.TVIF.HANDLE); tvItem.hItem = itemHwnd; tvItem.pszText = (IntPtr)(lpRemoteBuffer.ToInt32() + Marshal.SizeOf(typeof(Win32.TVITEM))); tvItem.cchTextMax = 1024; // Copy the local LVITEM to the remote buffer bSuccess = Win32.WriteProcessMemory(hProcess, lpRemoteBuffer, ref tvItem, Marshal.SizeOf(typeof(Win32.TVITEM)), 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 Win32.SendMessage((System.IntPtr)handle, (int)Win32.TVM.GETITEM, itemHwnd, lpRemoteBuffer); // Read the struct back from the remote process into local buffer bSuccess = Win32.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.PtrToStringAuto((IntPtr)(lpLocalBuffer.ToInt32() + Marshal.SizeOf(typeof(Win32.TVITEM)))); } catch (Exception e) { // If an exception occurred, return the error string retval = e.Message; } finally { // Make sure to clean up memory buffers! if(lpLocalBuffer != IntPtr.Zero) Marshal.FreeHGlobal( lpLocalBuffer ); if(lpRemoteBuffer != IntPtr.Zero) Win32.VirtualFreeEx(hProcess, lpRemoteBuffer, 0, Win32.MEM_RELEASE); if( hProcess != IntPtr.Zero ) Win32.CloseHandle(hProcess); } // Return what we found return retval; }
/// <summary> /// Returns the text for a specific item /// </summary> /// <param name="hWnd"></param> /// <param name="text"></param> /// <returns></returns> public string GetItemText(int itemHwnd) { const int dwBufferSize = 1024; int dwProcessID; Win32.TVITEM tvItem; string retval; bool bSuccess; IntPtr hProcess = IntPtr.Zero; IntPtr lpRemoteBuffer = IntPtr.Zero; IntPtr lpLocalBuffer = IntPtr.Zero; IntPtr threadId = IntPtr.Zero; try { tvItem = new Win32.TVITEM(); // Allocate a buffer in the local process lpLocalBuffer = Marshal.AllocHGlobal(dwBufferSize); // Get the process id owning the treeview threadId = Win32.GetWindowThreadProcessId(handle, out dwProcessID); if ((threadId == IntPtr.Zero) || (dwProcessID == 0)) { throw new ArgumentException("Could not found thread process id"); } // Open the process with all access hProcess = Win32.OpenProcess(Win32.PROCESS_ALL_ACCESS, false, dwProcessID); if (hProcess == IntPtr.Zero) { throw new ApplicationException("Failed to access process"); } // Allocate a buffer in the remote process lpRemoteBuffer = Win32.VirtualAllocEx(hProcess, IntPtr.Zero, dwBufferSize, Win32.MEM_COMMIT, Win32.PAGE_READWRITE); if (lpRemoteBuffer == IntPtr.Zero) { throw new SystemException("Failed to allocate memory in remote process"); } // Fill in the TVITEM struct, this is in your own process // Set the pszText member to somewhere in the remote buffer, // In this case we use the address imediately following the TVITEM stuct tvItem.mask = ((int)Win32.TVIF.TEXT | (int)Win32.TVIF.HANDLE); tvItem.hItem = itemHwnd; tvItem.pszText = (IntPtr)(lpRemoteBuffer.ToInt32() + Marshal.SizeOf(typeof(Win32.TVITEM))); tvItem.cchTextMax = 1024; // Copy the local LVITEM to the remote buffer bSuccess = Win32.WriteProcessMemory(hProcess, lpRemoteBuffer, ref tvItem, Marshal.SizeOf(typeof(Win32.TVITEM)), 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 Win32.SendMessage((System.IntPtr)handle, (int)Win32.TVM.GETITEM, itemHwnd, lpRemoteBuffer); // Read the struct back from the remote process into local buffer bSuccess = Win32.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.PtrToStringAuto((IntPtr)(lpLocalBuffer.ToInt32() + Marshal.SizeOf(typeof(Win32.TVITEM)))); } catch (Exception e) { // If an exception occurred, return the error string retval = e.Message; } finally { // Make sure to clean up memory buffers! if (lpLocalBuffer != IntPtr.Zero) { Marshal.FreeHGlobal(lpLocalBuffer); } if (lpRemoteBuffer != IntPtr.Zero) { Win32.VirtualFreeEx(hProcess, lpRemoteBuffer, 0, Win32.MEM_RELEASE); } if (hProcess != IntPtr.Zero) { Win32.CloseHandle(hProcess); } } // Return what we found return(retval); }