问题
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: 'Attempted to read or write protected memory. This is often an indication that other memory is corrupt.'
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: 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);
}
}
回答1:
IntPtr iptr = Marshal.AllocHGlobal(buff.Length);
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.
来源:https://stackoverflow.com/questions/43759645/whats-wrong-with-this-unmanaged-code-in-c