繁体   English   中英

C#-无法将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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM