here is a class That I converted from c++ to C# to read external treeview for C# programmer
- Code: Select all
public class CrossProcessMemory
{
const int TVM_GETITEM = 0x110C;
const int TVM_SETITEM = 0x110D;
const int TVIF_TEXT = 0x0001;
const uint PROCESS_ALL_ACCESS = (uint)(0x000F0000L | 0x00100000L | 0xFFF);
const uint MEM_COMMIT = 0x1000;
const uint MEM_RELEASE = 0x8000;
const uint PAGE_READWRITE = 0x04;
public const int TV_FIRST = 0x1100;
const int TVM_GETNEXTITEM = (TV_FIRST + 10);
const int TVGN_ROOT = 0x0;
const int TVGN_NEXT = 0x1;
const int TVGN_CHILD = 0x4;
const int MY_MAXLVITEMTEXT = 260;
[DllImport("user32.dll")]
static extern bool SendMessage(IntPtr hWnd, Int32 msg, Int32 wParam, IntPtr lParam);
[DllImport("user32.dll")]
public static extern int SendMessage(
IntPtr hWnd, // handle to destination window
int Msg, // message
uint wParam, // first message parameter
IntPtr lParam // second message parameter
);
[DllImport("user32")]
static extern IntPtr GetWindowThreadProcessId(IntPtr hWnd, out int lpwdProcessID);
[DllImport("kernel32")]
static extern IntPtr OpenProcess(uint dwDesiredAccess, bool bInheritHandle,
int dwProcessId);
[DllImport("kernel32")]
static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress,
int dwSize, uint flAllocationType, uint flProtect);
[DllImport("kernel32")]
static extern bool VirtualFreeEx(IntPtr hProcess, IntPtr lpAddress, int dwSize,
uint dwFreeType);
[DllImport("kernel32")]
static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress,
ref TV_ITEM buffer, int dwSize, IntPtr lpNumberOfBytesWritten);
[DllImport("kernel32")]
static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress,
IntPtr lpBuffer, int dwSize, IntPtr lpNumberOfBytesRead);
[DllImport("kernel32")]
static extern bool CloseHandle(IntPtr hObject);
[StructLayout(LayoutKind.Sequential)]
public struct TV_ITEM
{
public int mask;
public int hItem;
public int state;
public int stateMask;
public IntPtr pszText; //if string, must be preallocated
public int cchTextMax;
public int iImage;
public int iSelectedImage;
public int cChildren;
public int lParam;
public int iIntegral;
}
public static string ReadTreeViewItem(IntPtr hWnd)
{
const int dwBufferSize = 1024;
int dwProcessID;
string retval="";
IntPtr hProcess = IntPtr.Zero;
IntPtr lpRemoteBuffer = IntPtr.Zero;
IntPtr lpLocalBuffer = IntPtr.Zero;
IntPtr threadId = IntPtr.Zero;
int item = SendMessage(hWnd, TVM_GETNEXTITEM, (uint)0, IntPtr.Zero);
try
{
lpLocalBuffer = Marshal.AllocHGlobal(dwBufferSize);
// Get the process id owning the window
threadId = GetWindowThreadProcessId(hWnd, 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");
ExtractNode(hProcess, hWnd, item, lpLocalBuffer, lpRemoteBuffer, dwBufferSize);
}
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;
}
static void ExtractNode(IntPtr hProcess, IntPtr hTreeview, int iItem, IntPtr lpLocalBuffer, IntPtr lpRemoteBuffer, int dwBufferSize)
{
bool bSuccess;
string retval;
while (iItem > 0)
{
TV_ITEM tvItem = new TV_ITEM();
// Fill in the TVITEM 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 TVITEM stuct
tvItem.mask = TVIF_TEXT;
tvItem.hItem = iItem;
tvItem.pszText = (IntPtr)(lpRemoteBuffer.ToInt32() + Marshal.SizeOf(typeof(TV_ITEM)));
tvItem.cchTextMax = 255;
// Copy the local TVITEM to the remote buffer
bSuccess = WriteProcessMemory(hProcess, lpRemoteBuffer, ref tvItem,
Marshal.SizeOf(typeof(TV_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(hTreeview, TVM_GETITEM, 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 TV_ITEM structure
// the next line extracts the text from the buffer into a managed string
retval = Marshal.PtrToStringAnsi((IntPtr)(lpLocalBuffer.ToInt32() +
Marshal.SizeOf(typeof(TV_ITEM))));
System.Windows.Forms.MessageBox.Show(retval);
if (iItem > 0)
{
int iChildItem = SendMessage(hTreeview, TVM_GETNEXTITEM, (uint)TVGN_CHILD, (IntPtr)iItem);
if(iChildItem>0)
ExtractNode(hProcess, hTreeview, iChildItem, lpLocalBuffer, lpRemoteBuffer, dwBufferSize);
}
iItem = SendMessage(hTreeview, TVM_GETNEXTITEM, (uint)TVGN_NEXT, (IntPtr)iItem);
}
}
}
and test this class like this
- Code: Select all
CrossProcessMemory.ReadTreeViewItem(hTreeview);
happy now





