【发布时间】:2014-02-12 01:40:14
【问题描述】:
在运行包含多个 PInvokes 的 silverlight 5.0 应用程序 5 分钟左右后,我收到以下错误:
Attempted to read or write protected memory
很可能,我在某个地方遇到了内存泄漏。
问题是如何调试它?我根本没有得到堆栈跟踪,所以我无法准确定位有问题的代码。
通过多次注释代码和重新运行应用程序,我想我设法找到了问题,但我无法找出问题所在。
潜在违规代码:
private void InitUSBEvents()
{
const string clsName = "SLUsbClass";
const string wndName = "SLUsbWindow";
Win32.WNDCLASSEX wndClassEx = new Win32.WNDCLASSEX();
wndClassEx.cbSize = Marshal.SizeOf(wndClassEx);
wndClassEx.lpszClassName = clsName;
wndClassEx.lpfnWndProc = WndProc;
rClassAtomValue = Win32.RegisterClassEx2(ref wndClassEx);
windowHandle = Win32.CreateWindowEx2(0, rClassAtomValue, wndName, 0, 0, 0, 0, 0, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
Win32Usb.RegisterKeyboardUsbEvents(windowHandle);
}
[AllowReversePInvokeCalls]
private IntPtr WndProc(IntPtr hWnd, WM msg, IntPtr wParam, IntPtr lParam)
{
switch (msg)
{
case WM.INPUT:
//Console.WriteLine("Key Event");
break;
default:
return Win32.DefWindowProc(hWnd, msg, wParam, lParam);
}
return IntPtr.Zero;
}
PInvoke 相关声明:
public class Win32
{
[DllImport("user32.dll", SetLastError = true, EntryPoint = "CreateWindowEx")]
public static extern IntPtr CreateWindowEx(
WindowStylesEx dwExStyle,
string lpClassName,
string lpWindowName,
WindowStyles dwStyle,
int x,
int y,
int nWidth,
int nHeight,
IntPtr hWndParent,
IntPtr hMenu,
IntPtr hInstance,
IntPtr lpParam);
// Create a window, but accept a atom value.
[DllImport("user32.dll", SetLastError = true, EntryPoint = "CreateWindowEx")]
public static extern IntPtr CreateWindowEx2(
WindowStylesEx dwExStyle,
UInt16 lpClassName,
string lpWindowName,
WindowStyles dwStyle,
int x,
int y,
int nWidth,
int nHeight,
IntPtr hWndParent,
IntPtr hMenu,
IntPtr hInstance,
IntPtr lpParam);
[DllImport("kernel32.dll", EntryPoint = "LocalAlloc")]
internal static extern IntPtr LocalAlloc_NoSafeHandle(
LocalMemoryFlags uFlags, IntPtr sizetdwBytes);
[DllImport("kernel32.dll", SetLastError = true)]
internal static extern IntPtr LocalFree(IntPtr hMem);
[DllImport("user32.dll", SetLastError = true, EntryPoint = "RegisterClassEx")]
public static extern UInt16 RegisterClassEx2([In] ref WNDCLASSEX lpwcx);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.U2)]
public static extern short RegisterClassEx([In] ref WNDCLASSEX lpwcx);
[DllImport("user32.dll")]
public static extern IntPtr DefWindowProc(IntPtr hWnd, WM uMsg, IntPtr wParam, IntPtr lParam);
}
public class Win32Usb
{
public static bool RegisterKeyboardUsbEvents(IntPtr hWnd)
{
//Create an array of all the raw input devices we want to
//listen to. In this case, only keyboard devices.
//RIDEV_INPUTSINK determines that the window will continue
//to receive messages even when it doesn't have the focus.
RAWINPUTDEVICE[] rid = new RAWINPUTDEVICE[1];
rid[0].usUsagePage = 0x01;
rid[0].usUsage = 0x06;
rid[0].dwFlags = RIDEV_INPUTSINK;
rid[0].hwndTarget = hWnd;
return RegisterRawInputDevices(rid, (uint)rid.Length, (uint)Marshal.SizeOf(rid[0]));
}
[StructLayout(LayoutKind.Explicit)]
internal class RAWINPUT
{
[FieldOffset(0)]
public RAWINPUTHEADER header;
[FieldOffset(16)]
public RAWMOUSE mouse;
[FieldOffset(16)]
public RAWKEYBOARD keyboard;
[FieldOffset(16)]
public RAWHID hid;
}
[StructLayout(LayoutKind.Sequential)]
internal class RAWINPUTDEVICELIST
{
public IntPtr hDevice;
[MarshalAs(UnmanagedType.U4)]
public int dwType;
}
[StructLayout(LayoutKind.Sequential)]
internal struct RAWINPUTDEVICE
{
[MarshalAs(UnmanagedType.U2)]
public ushort usUsagePage;
[MarshalAs(UnmanagedType.U2)]
public ushort usUsage;
[MarshalAs(UnmanagedType.U4)]
public int dwFlags;
public IntPtr hwndTarget;
}
}
我也找不到 PInvoke 声明有什么问题。在 Silverlight 上调试与 PInvoke 相关的错误有哪些好的策略?或者有没有办法强制堆栈跟踪输出? (我已经尝试在Debug->Exception中打开所有要抛出的异常)
【问题讨论】:
-
您的大部分
MarshalAs属性都可以删除。在我看来,它们只是增加了噪音。
标签: c# .net silverlight winapi pinvoke