[英]Get Treeview(SysTreeView32) items text using win32 api
I am writing an application to automate some repetitive tasks at my job. 我正在编写一个应用程序,以使工作中的某些重复性任务自动化。 One of the task I wish to do, is to be able to automate the process of creating a recovery drive from "RecoveryDrive.exe" in windows 10. All the process is done, but at one step, a human need to select the drive in a SysTreeView32 control.
我要执行的任务之一是能够自动从Windows 10中的“ RecoveryDrive.exe”创建恢复驱动器的过程。所有过程都已完成,但是第一步,人类需要选择驱动器在SysTreeView32控件中。
I have tried to find how to get the text of the current selected treeNodeItem. 我试图找到如何获取当前选定的treeNodeItem的文本。
I have the handle of the control, but when I try to read it, using a code sample found online, the recoveryDrive application crash. 我拥有该控件的句柄,但是当我尝试使用在线找到的代码示例读取它时,recoveryDrive应用程序崩溃。
I'm suspecting this have to do with 64bits/32bits mismatch with the api methods I'm using and maybe ASCI and Unicode encoding mismatch ... I also think I need to use LocalAlloc inside of the target app Handle or memory 我怀疑这与我使用的api方法的64位/ 32位不匹配以及ASCI和Unicode编码不匹配有关...我也认为我需要在目标应用的句柄或内存中使用LocalAlloc
here is the pasteBin of the code in the present state . 这是当前状态下的代码的pasteBin 。
It also have the 3 page I have based my code from. 它也有我基于我的代码的3页。 The app crash in the GetTreeItemText function when I'm using the sendMessage.
当我使用sendMessage时,应用程序在GetTreeItemText函数中崩溃。
I have found some example on how to do this in C++, but I don't really understand it. 我找到了一些有关如何在C ++中执行此操作的示例,但我不太了解。
public static string GetTreeItemText(IntPtr treeViewHwnd, IntPtr hItem)
{
int ret;
TVITEM tvi = new TVITEM();
IntPtr pszText = LocalAlloc(0x40, MY_MAXLVITEMTEXT);
tvi.mask = TVIF_TEXT;
tvi.hItem = hItem;
tvi.cchTextMax = MY_MAXLVITEMTEXT;
tvi.pszText = pszText;
ret = SendMessageTVI(treeViewHwnd, TVM_GETITEM, 0, ref tvi);
string buffer = Marshal.PtrToStringUni((IntPtr)tvi.pszText,
MY_MAXLVITEMTEXT);
//char[] arr = buffer.ToCharArray(); //<== use this array to look at the bytes in debug mode
LocalFree(pszText);
return buffer;
}
The LPARAM
of the TVM_GETITEM
message is a pointer to a TVITEM
structure. TVM_GETITEM
消息的LPARAM
是指向TVITEM
结构的指针。 The thing is, that structure MUST be allocated in the same process that owns the TreeView control. 问题是,必须在拥有TreeView控件的同一进程中分配该结构。 So, when sending
TVM_GETITEM
across process boundaries, you must use VirtualAllocEx()
to allocate the TVITEM
and its pszText
buffer in the address space of the target process, and then use WriteProcessMemory()
/ ReadProcessMemory()
to write/read that structure's data. 因此,跨进程边界发送
TVM_GETITEM
时,必须使用VirtualAllocEx()
在目标进程的地址空间中分配TVITEM
及其pszText
缓冲区,然后使用WriteProcessMemory()
/ ReadProcessMemory()
来写入/读取该结构的数据。
Try something like this (you can find declarations for the Win32 API functions used at PInvoke.net ): 尝试这样的操作(您可以在PInvoke.net上找到Win32 API函数的声明 ):
public static string GetTreeItemText(IntPtr treeViewHwnd, IntPtr hItem)
{
string itemText;
uint pid;
GetWindowThreadProcessId(treeViewHwnd, out pid);
IntPtr process = OpenProcess(ProcessAccessFlags.VirtualMemoryOperation | ProcessAccessFlags.VirtualMemoryRead | ProcessAccessFlags.VirtualMemoryWrite | ProcessAccessFlags.QueryInformation, false, pid);
if (process == IntPtr.Zero)
throw new Exception("Could not open handle to owning process of TreeView", new Win32Exception());
try
{
uint tviSize = Marshal.SizeOf(typeof(TVITEM));
uint textSize = MY_MAXLVITEMTEXT;
bool isUnicode = IsWindowUnicode(treeViewHwnd);
if (isUnicode)
textSize *= 2;
IntPtr tviPtr = VirtualAllocEx(process, IntPtr.Zero, tviSize + textSize, AllocationType.Commit, MemoryProtection.ReadWrite);
if (tviPtr == IntPtr.Zero)
throw new Exception("Could not allocate memory in owning process of TreeView", new Win32Exception());
try
{
IntPtr textPtr = IntPtr.Add(tviPtr, tviSize);
TVITEM tvi = new TVITEM();
tvi.mask = TVIF_TEXT;
tvi.hItem = hItem;
tvi.cchTextMax = MY_MAXLVITEMTEXT;
tvi.pszText = textPtr;
IntPtr ptr = Marshal.AllocHGlobal(tviSize);
try
{
Marshal.StructureToPtr(tvi, ptr, false);
if (!WriteProcessMemory(process, tviPtr, ptr, tviSize, IntPtr.Zero))
throw new Exception("Could not write to memory in owning process of TreeView", new Win32Exception());
}
finally
{
Marshal.FreeHGlobal(ptr);
}
if (SendMessage(treeViewHwnd, isUnicode ? TVM_GETITEMW : TVM_GETITEMA, 0, tviPtr) != 1)
throw new Exception("Could not get item data from TreeView");
ptr = Marshal.AllocHGlobal(textSize);
try
{
int bytesRead;
if (!ReadProcessMemory(process, textPtr, ptr, textSize, out bytesRead))
throw new Exception("Could not read from memory in owning process of TreeView", new Win32Exception());
if (isUnicode)
itemText = Marshal.PtrToStringUni(ptr, bytesRead / 2);
else
itemText = Marshal.PtrToStringAnsi(ptr, bytesRead);
}
finally
{
Marshal.FreeHGlobal(ptr);
}
}
finally
{
VirtualFreeEx(process, tviPtr, 0, FreeType.Release);
}
}
finally
{
CloseHandle(process);
}
//char[] arr = itemText.ToCharArray(); //<== use this array to look at the bytes in debug mode
return itemText;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.