这行代码令我感到困惑!
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中使用此代码(以及其余部分)时,代码返回一个不正确的字符串。它看起来是空的,但实际上并不是空的。也许只是空白......
有没有人有过这种麻烦编组的类似经历?现在好三个小时让我感到困惑......
非常感谢任何帮助或任何想法或任何想法!
答案 0 :(得分:0)
您似乎正在尝试读取另一个进程的内存。您正在向列表视图控件发送LV_GETITEM
消息。这要求您在该其他进程的虚拟地址空间中分配内存。您对VirtualAllocEx
的调用所做的。
到目前为止一直很好,但这里是踢球者。您需要将分配的结构作为目标进程的正确布局。现在,让我们假设目标进程是64位进程。在这种情况下,struct包含64位指针。当您的进程也是64位时,您定义的结构将具有64位指针。但是当你的进程是32位时,结构中的任何指针都是32位。
因此,现在我们遇到这样一种情况,即进程中的结构与目标进程中的结构具有不同的布局。这种不匹配足以使所有这些努力失败。为了有机会完成这项工作,您需要声明您的结构,使其布局与64位布局相匹配。鉴于您只访问少数字段,分配正确大小的内存块(可能是字节数组)并手动读取/写入字段可能更简单。并避免使用struct marshalling。
即便如此,我怀疑32位进程是否能够以这种方式进行64位进程。您可以在另一个方向上执行此操作,从64位进程到32位进程。但是我已经尝试过,并且从未在你正在尝试的方向上取得成功。
所有迹象表明,您应该坚持使用64位进程执行此任务。或者找到一种官方支持的方式来做你正在做的事情。例如,如果您只是想阅读资源管理器视图的内容,那么就有一个shell API。
顺便说一句,请停止使用魔术常量而不是消息标识符名称。没有人喜欢尝试理解0x1005
的含义。声明一个名为LV_GETITEM
的常量。您似乎也根本不执行任何错误检查。这也会让你的生活变得艰难。如果其中一个API调用失败,您将如何找到它?