C# 中的这段非托管代码有什么问题? [英] What's wrong with this unmanaged code in C#?
问题描述
我试图从层次结构中的每个控件中获取文本.如果我使用 unsafe
方法,以下代码运行良好.但是,使用非托管版本似乎会破坏 hWnd
,结果 hWnd = GetAncestor(hWnd, GetAncestorFlags.GA_PARENT)
抱怨:
I was trying to get text from each control in hierarchy. The following code runs fine if I use the unsafe
method. However, using the unmanaged version seems to break hWnd
, which in result hWnd = GetAncestor(hWnd, GetAncestorFlags.GA_PARENT)
complains:
System.AccessViolationException: '试图读取或写入受保护的内存.这通常表明其他内存已损坏.'
我已经检查了 hWnd
在从 GetWindowTextRaw
函数返回后没有改变,如果我注释掉这个函数中的第二个 SendMessage
将不会导致问题(虽然它显然不会得到窗口文本).
I have checked hWnd
was not changed after returning from GetWindowTextRaw
function, and if I comment out the second SendMessage
in this function will not cause the issue (although it will clearly not get the window text).
(PS:我在 NuGet 中使用 PInvoke.User32)
(PS: I'm using PInvoke.User32 in NuGet)
// using static PInvoke.User32;
public static string GetWindowTextRaw(IntPtr hWnd) {
// Allocate correct string length first
int length = (int)SendMessage(hWnd, WindowMessage.WM_GETTEXTLENGTH, IntPtr.Zero, IntPtr.Zero);
char[] buff = new char[length + 1];
IntPtr iptr = Marshal.AllocHGlobal(buff.Length);
SendMessage(hWnd, WindowMessage.WM_GETTEXT, (IntPtr)(length + 1), iptr);
Marshal.Copy(iptr, buff, 0, length + 1);
Marshal.FreeHGlobal(iptr);
//unsafe
//{
// fixed (char* p = buff)
// SendMessage(hWnd, WindowMessage.WM_GETTEXT, (IntPtr)(length + 1), (IntPtr)p);
//}
return new string(buff).TrimEnd('\0');
}
private void button1_Click(object sender, EventArgs {
POINT p;
IntPtr hWnd;
//while (true)
if (GetCursorPos(out p)) {
hWnd = WindowFromPoint(p); ;
Debug.Print($"{p.x} {p.y} 0x{(int)hWnd:x8}");
while (hWnd != IntPtr.Zero) {
Debug.Print($"{GetWindowTextRaw(hWnd)}");
hWnd = GetAncestor(hWnd, GetAncestorFlags.GA_PARENT);
}
Thread.Sleep(500);
}
}
推荐答案
IntPtr iptr = Marshal.AllocHGlobal(buff.Length);
尺寸错误,需要buff.Length * sizeof(char)
.是现在分配的两倍.正如所写,代码破坏了操作系统使用的同一个堆,接下来可能会发生任何事情.AVE 是正常且快乐的结果,但不能保证.
Wrong size, you need buff.Length * sizeof(char)
. Twice as much as it allocates now. As written, the code corrupts the same heap that the OS uses, anything can happen next. An AVE is a normal and happy outcome, but not guaranteed.
这篇关于C# 中的这段非托管代码有什么问题?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!