3

我整晚都在和这个作斗争。我只是不知道有什么问题。我正在尝试获取桌面图标+标题大小。我有一些函数可以找到桌面句柄并将其放入名为 SysListView32_hwnd 的变量中。我已经用 Windows 间谍程序验证了它是正确的。这是我遇到问题的部分。

Rectangle rct = new Rectangle();
IntPtr pRct = Marshal.AllocHGlobal(Marshal.SizeOf(rct));
Marshal.StructureToPtr(rct, pRct, true);

SendMessage(SysListView32_hwnd, LVM_GETITEMRECT, (IntPtr)0, pRct);

Rectangle Rect = (Rectangle)Marshal.PtrToStructure(pRct, typeof(Rectangle));
Marshal.FreeHGlobal(pRct);
Debug.WriteLine(Rect.Height + "    " + Rect.Width);

每次都会让资源管理器崩溃。C# Visual Studio 2010 Windows 7 x64,我正在编译为 64 位程序

如果需要,这是我的完整应用程序

4

2 回答 2

2

这解决了对问题进行广泛编辑时提出的其他问题。

在我看来,我们正在使用LVITEMsVirtualAllocEx指定sizeof(uint).

dwSize在 MSDN 上的参数文档中VirtualAllocEx()指出:

要分配的内存区域的大小,以字节为单位。

如果 lpAddress 为 NULL,则函数将 dwSize 向上舍入到下一页边界。

如果 lpAddress 不为 NULL,则该函数分配包含从 lpAddress 到 lpAddress+dwSize 范围内的一个或多个字节的所有页面。这意味着,例如,跨越页面边界的 2 字节范围会导致函数分配两个页面。

换句话说,它分配整个页面。因为一个页面是 4KB,所以你很幸运。您应该确保dwSize对于您需要的缓冲区足够大。

为什么 pszText = (IntPtr)((int)lpBaseAddress + Marshal.SizeOf(typeof(LVITEM)))?那不只是指向结构的结尾吗。

是的,它确实指向结构的结尾。关键是必须指向调用者分配的缓冲区pszTextLVITEM编写此代码的人选择使用结构末尾的备用缓冲区空间。由于该结构声明pszText包含 256 个字节,因此很容易放入 4KB 页面的剩余部分。所以它有效,但它有点不透明。

于 2011-09-17T07:16:25.210 回答
1

这解决了广泛编辑之前的原始问题。

它失败了,因为您编写它的方式只有在您从拥有目标窗口句柄的进程中调用时才能工作。这是因为您传递了一个指针,但这仅在您的进程中有效。一旦它进入另一个进程,它就会引用一个无意义的地址。即使它确实意味着什么,一个进程也无法在系统的帮助下读取另一个进程的内存。自然是探险者炸弹。

解决方法是VirtualAllocEx()在资源管理器进程中使用分配内存。然后发送消息。然后使用ReadProcessMemory()将 rect 的内容编组回您的进程。最常引用的代码示例是此代码项目文章。该示例正在使用LVM_GETITEMTEXT,但原理相同。

于 2011-09-16T16:55:08.883 回答