![](/img/trans.png)
[英]Cannot Marshal C++ char[] to C# string using Marshal.PtrToStringAuto(IntPtr)
[英]C# - Cannot Marshal IntPtr To String Correctly
这行代码让我感到困惑!
string s = Marshal.PtrToStringAnsi((IntPtr)((Int32)Buffer +
Marshal.SizeOf(typeof(Struct))));
这是其余的功能。
Api.LvItem lvItem = new Api.LvItem();
IntPtr lpLocalBuffer = Marshal.AllocHGlobal(1024);
uint pid;
uint thread = Api.GetWindowThreadProcessId(hWnd, out pid);
IntPtr hProcess = Api.OpenProcess(0x001f0fff, false, (int)pid);
IntPtr lpRemoteBuffer = Api.VirtualAllocEx(hProcess, IntPtr.Zero, 1024, 0x1000, 4);
lvItem.mask = 1;
lvItem.iItem = index;
lvItem.iSubItem = subitem;
lvItem.pszText = (IntPtr)((int)lpRemoteBuffer + Marshal.SizeOf(typeof(Api.LvItem)));
lvItem.cchTextMax = 50;
Api.WriteProcessMemory(hProcess, lpRemoteBuffer, ref lvItem, Marshal.SizeOf(typeof(Api.LvItem)), 0);
Api.SendMessage(hWnd, 0x1005, IntPtr.Zero, lpRemoteBuffer);
Api.ReadProcessMemory(hProcess, lpRemoteBuffer, lpLocalBuffer, 1024, 0);
string ret = Marshal.PtrToStringAnsi((IntPtr)((int)lpLocalBuffer + Marshal.SizeOf(typeof(Api.LvItem))));
Marshal.FreeHGlobal((IntPtr)lpLocalBuffer);
Api.VirtualFreeEx(hProcess, lpRemoteBuffer, 0, 0x8000);
Api.CloseHandle(hProcess);
return ret;
此代码用于获取另一个进程的列表视图中每个项目的文本。 我从这里遵循代码(半): http : //taylorza.blogspot.com/2009/08/archive-hacking-my-way-across-process.html
对0x1005的使用感到抱歉。 这是LV_GETITEM
消息的代码。
我将其范围缩小到与平台相关。 它适用于x64和AnyCPU,而不适用于x86。 我将如何更改内存分配等中的大小差异
在控制台应用程序中使用时,它会正确返回该值。 但是,当我在通过反射调用的.DLL中使用此代码(及其其余部分)时,该代码返回的字符串不正确。 它显示为空,但实际上不为空。 也许只是空白...
有没有人遇到过类似的麻烦编组经验? 现在已经困扰了我三个小时了...
任何帮助或任何想法或任何东西都将不胜感激!
看来您正在尝试读取另一个进程的内存。 您正在将LV_GETITEM
消息发送到列表视图控件。 这要求您在该其他进程的虚拟地址空间中分配内存。 您对VirtualAllocEx
的调用做了什么。
到目前为止,一切都很好,但这是关键。 您需要分配的结构才能成为目标进程的正确布局。 现在,让我们假设目标进程是一个64位进程。 在这种情况下,该结构包含64位指针。 当您的进程也是64位时,则您定义的结构将具有64位指针。 但是,当您的进程是32位时,该结构中的任何指针都将是32位。
因此,现在我们遇到一种情况,您的流程中的结构与目标流程中的结构具有不同的布局。 这种不匹配足以使所有这些努力失败。 为了有机会进行这项工作,您需要声明结构,以使其布局与64位布局匹配。 假设您只访问少数几个字段,那么分配一个适当大小的内存块(也许是字节数组)并手动读取/写入字段可能会更简单。 并避免结构编组。
即使那样,我仍然怀疑32位进程是否能够以这种方式戳入64位进程。 您可以从64位处理到32位处理的另一方向进行操作。 但是我已经尝试过并且从未成功地朝着您尝试的方向发展。
所有迹象表明,您应该坚持执行此任务的64位进程。 或者,找到一种官方支持的方式来做您正在做的事情。 例如,如果您只想阅读资源管理器视图的内容,则有一个Shell API。
另外,请停止使用魔术常数而不是消息标识符名称。 没有人喜欢尝试理解0x1005
含义。 声明一个名为LV_GETITEM
的常量。 您似乎也根本不执行任何错误检查。 这也将使您的生活艰难。 如果其中一个API调用失败,您将如何找到呢?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.