C# 中的这个非托管代码有什么问题?
What's wrong with this unmanaged code in C#?
我试图从层次结构中的每个控件获取文本。如果我使用 unsafe
方法,下面的代码运行良好。但是,使用非托管版本似乎会中断 hWnd
,结果 hWnd = GetAncestor(hWnd, GetAncestorFlags.GA_PARENT)
抱怨:
System.AccessViolationException: 'Attempted to read or write protected memory. This is often an indication that other memory is corrupt.'
我检查过 hWnd
在从 GetWindowTextRaw
函数返回后没有改变,如果我注释掉这个函数中的第二个 SendMessage
将不会导致问题(尽管它会显然没有得到 window 文本)。
(PS: 我在 NuGet 中使用 PInvoke.User32)
// 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('[=10=]');
}
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)
。是现在分配的两倍。正如所写,代码破坏了 OS 使用的同一个堆,接下来任何事情都可能发生。 AVE 是一个正常而快乐的结果,但不能保证。
我试图从层次结构中的每个控件获取文本。如果我使用 unsafe
方法,下面的代码运行良好。但是,使用非托管版本似乎会中断 hWnd
,结果 hWnd = GetAncestor(hWnd, GetAncestorFlags.GA_PARENT)
抱怨:
System.AccessViolationException: 'Attempted to read or write protected memory. This is often an indication that other memory is corrupt.'
我检查过 hWnd
在从 GetWindowTextRaw
函数返回后没有改变,如果我注释掉这个函数中的第二个 SendMessage
将不会导致问题(尽管它会显然没有得到 window 文本)。
(PS: 我在 NuGet 中使用 PInvoke.User32)
// 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('[=10=]');
}
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)
。是现在分配的两倍。正如所写,代码破坏了 OS 使用的同一个堆,接下来任何事情都可能发生。 AVE 是一个正常而快乐的结果,但不能保证。