Read External Treeview Example in C#

This topic contains 2 replies, has 3 voices, and was last updated by  method 9 years, 4 months ago.

  • Author
    Posts
    1 Star2 Stars3 Stars4 Stars5 Stars Rate it First!
  • #14209
    Member
    Posts: 521

    here is a class That I converted from c++ to C# to read external treeview for C# programmer 😀 , I still hate vb, poor loco :mrgreen:

     

    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

    CrossProcessMemory.ReadTreeViewItem(hTreeview);

    happy now :mrgreen:

    #34410
    Member
    Posts: 165

    buy me some tacos

    #34411
    Member
    Posts: 623

    Departure could you show me how i can select a perticule item in treeview assuming i have the handle of treeview in VB6?Thanks in advance.

You must be logged in to reply to this topic.