当前位置: 首页 > 编程语言 > C#

DetectedCallbackOnCollectedDelegateinglobalKeyboardHook分享

时间:2023-04-10 22:34:15 C#

DetectedCallbackOnCollectedDelegateinglobalKeyboardHook此类允许检查是否在任何地方按下了键盘键。过了一段时间我有一个错误:**检测到CallbackOnCollectedDelegate**对类型为“Browser!Utilities.globalKeyboardHook+keyboardHookProc::Invoke”的垃圾收集委托进行了回调。这可能会导致应用程序崩溃、损坏和数据丢失。将委托传递给非托管代码时,它们必须由托管应用程序保持活动状态,直到保证它们永远不会被调用。这是globalkeyboardHook类:publicdelegateintkeyboardHookProc(intcode,intwParam,refkeyboardHookStructlParam);publicstructkeyboardHookStruct{publicintvkCode;公共int扫描代码;公共int标志;公共时间;公共诠释dwExtraInfo;}constintWH_KEYBOARD_LL=13;constintWM_KEYDOWN=0x100;constintWM_KEYUP=0x101;constintWM_SYSKEYDOWN=0x104;constintWM_SYSKEYUP=0x105;publicListHookedKeys=newList();IntPtrhhook=IntPtr.Zero;公共事件KeyEventHandlerKeyDown;公共事件KeyEventHandlerKeyUp;公共全球键盘dHook(){挂钩();}~globalKeyboardHook(){unhook();}publicvoidhook(){IntPtrhInstance=LoadLibrary("User32");hhook=SetWindowsHookEx(WH_KEYBOARD_LL,hookProc,hInstance,0);}publicvoidunhook(){UnhookWindowsHookEx(hhook);}publicinthookProc(intcode,intwParam,refkeyboardHookStructlParam){if(code>=0){Keyskey=(Keys)lParam.vkCode;如果(HookedKeys.Contains(key)){KeyEventArgskea=newKeyEventArgs(key);如果((wParam==WM_KEYDOWN||wParam==WM_SYSKEYDOWN)&&(KeyDown!=null)){KeyDown(this,kea);}elseif((wParam==WM_KEYUP||wParam==WM_SYSKEYUP)&&(KeyUp!=null)){KeyUp(this,kea);}如果(kea.Handled)返回1;}}returnCallNextHookEx(hhook,code,wParam,reflParam);}[DllImport("user32.dll")]staticexternIntPtrSetWindowsHookEx(intidHook,keyboardHookProccallback,IntPtrhInstance,uintthreadId);[DllImport("user32.dll")]staticexternboolUnhookWindowsHookEx(IntPtrhInstance);[DllImport("user32.dll")]staticexternintCallNextHookEx(IntPtridHook,intnCode,intwParam,refkeyboardHookStructlParam);[DllImport("kernel32.dll")]staticexternIntPtrLoadLibrary(stringlpFileName);#endregion知道如何解决吗?程序运行正常,但过了一会儿程序冻结了,我得到了这个错误hhook=SetWindowsHookEx(WH_KEYBOARD_LL,hookProc,hInstance,0);这是你的问题。您依靠C#语法糖来自动创建hookProc的委托对象。实际的代码生成看起来像这样:keyboardHookProc$temp=newkeyboardHookProc(hookProc);hhook=SetWindowsHookEx(WH_KEYBOARD_LL,$temp,hInstance,0);只有一个对委托对象的引用,$temp。但它是一个局部变量,一旦您的hook()方法停止执行并返回,它就会消失。垃圾收集器看不到Windows对它有一个“引用”,它不能探测非托管代码以获取引用。因此,下次垃圾收集器运行时,委托对象将被销毁。当Windows执行挂钩回调时,这就是kaboom。内置的MDA会检测问题并在程序因AccessViolation而崩溃之前生成有用的诊断信息。您需要创建对足够长的委托对象的附加引用。例如,您可以使用GCHandle。或者更简单,只需自己存储引用,这样垃圾收集器就始终可以看到它。向您的班级添加一个字段。将其设置为静态是确保无法收集对象的可靠方法:privatestatickeyboardHookProccallbackDelegate;publicvoidhook(){if(callbackDelegate!=null)thrownewInvalidOperationException("不能多次挂钩");IntPtrhInstance=LoadLibrary("User32");callbackDelegate=newkeyboardHookProc(hookProc);hhook=SetWindowsHookEx(WH_KEYBOARD_LL,callbackDelegate,hInstance,0);如果(hhook==IntPtr.Zero)抛出新的Win32Exception();}publicvoidunhook(){if(callbackDelegate==null)返回;boolok=UnhookWindowsHookEx(hhook);如果(!ok)抛出新的Win32Exception();回调委托=空;无需pinvokeFreeLibrary,user32.dll始终加载,直到您的程序终止。以上为C#学习教程:检测到globalKeyboardHook中CallbackOnCollectedDelegate共享的所有内容。如果对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权请点击右侧联系管理员删除。如需转载请注明出处:

最新推荐
猜你喜欢