已经在C#中调用垃圾回收代理?我一直在使用我发现的这个关键钩子脚本,但在我的程序中使用它几秒钟后我仍然得到错误。错误说..已经对垃圾收集委托“键盘记录器”进行了调用!Utilities.globalKeyboardHook+keyboardHookProc::Invoke'。我怎样才能解决这个问题?对于钩子///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;#endregion#region实例变量//////要监视的键集合///publicListHookedKeys=newList();//////钩子的句柄,需要这个来取消钩子并调用下一个钩子///IntPtrhhook=IntPtr.Zero;#endregion#regionEvents//////当按下一个挂钩键时发生///publiceventKeyEventHand勒KeyDown;//////当其中一个挂钩键被释放时发生///publiceventKeyEventHandlerKeyUp;#endregion#region构造函数和析构函数//////初始化类的新实例并安装键盘挂钩。///publicglobalKeyboardHook(){挂钩();}//////在///被垃圾回收回收并卸载键盘挂钩之前,释放非托管资源并执行其他清理操作。///~globalKeyboardHook(){unhook();}#endregion#region公共方法//////安装全局钩子///publicvoidhook(){IntPtrhInstance=LoadLibrary("User32");hhook=SetWindowsHookEx(WH_KEYBOARD_LL,hookProc,hInstance,0);}//////卸载全局钩子///publicvoidunhook(){UnhookWindowsHookEx(hhook);}//////键盘钩子的回调//////钩子代码,如果它不是>=0,函数不应该做任何事情///事件类型///keyhook活动信息///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);}#endregion#regionDLLimports//////设置窗口挂钩,执行所需的事件,hInstance或threadId之一必须为非空//////要挂钩的事件的id///回调。///您要将事件附加到的句柄,可以为null///您要将事件附加到的线程,可以为null///所需挂钩的句柄[DllImport("user32.dll")]staticexternIntPtrSetWindowsHookEx(intidHook,keyboardHookProc回调,IntPtrhInstance,uintthreadId);//////解除窗口挂钩。//////从SetWindowsHookEx返回的钩子句柄///如果成功则为真,否则为假[DllImport("user32.dll")]staticexternboolUnhookWindowsHookEx(IntPtrhInstance);//////调用下一个钩子。//////钩子ID///钩子代码///wparam。///参数。///[DllImport("user32.dll")]staticexternintCallNextHookEx(IntPtridHook,intnCode,intwParam,refkeyboardHookStructlParam);//////加载库。//////库的名称///库的句柄[DllImport("kernel32.dll")]staticexternIntPtrLoadLibrary(stringlpFileName);#endregion}}globalKeyboardHook类:usingSystem;使用System.Collections.Generic;使用系统文本;使用System.Runtime.InteropServices;使用System.Windows.Forms;使用System.IO;namespaceUtilities{//////管理全局低级键盘钩子的类///classglobalKeyboardHo好的:IDisposable{privatebool_disposed;#region常量、结构和委托定义//////定义挂钩的回调类型///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;#endregion#region实例变量//////要监视的键集合///publicListHookedKeys=newList();//////钩子的句柄,需要这个来取消钩子并调用下一个钩子///IntPtrhhook=IntPtr.Zero;#endregion#regionEvents//////当按下一个挂钩键时发生///publiceventKeyEventHandlerKeyDown;//////当其中一个挂钩键被释放时发生///公共事件KeyEventHandlerKeyUp;#endregion#region构造函数和析构函数//////初始化类的新实例并安装键盘挂钩。///publicglobalKeyboardHook(){挂钩();_disposed=假;}publicvoidDispose(){Dispose(true);//如果此类型的子类//实现终结器,则使用SupressFinalize。GC.SuppressFinalize(这个);}protectedvirtualvoidDispose(booldisposing){//如果您需要线程安全,请在这些//操作以及使用该资源的方法中使用锁。if(!_disposed){if(处理){unhook();}//表明实例已经被释放。_disposed=真;}}//////在///被垃圾回收回收并卸载键盘挂钩之前,释放非托管资源并执行其他清理操作。///~globalKeyboardHook(){Dispose();}#endregion#region公共方法//////安装全局钩子///publicvoidhook(){IntPtrhInstance=LoadLibrary("User32");hhook=SetWindowsHookEx(WH_KEYBOARD_LL,newkeyboardHookProc(hookProc),hInstance,0);}//////卸载全局钩子///publicvoidunhook(){UnhookWindowsHookEx(hhook);}//////键盘钩子的回调//////钩子代码,如果它不是>=0,函数不应该做任何事情///事件类型///keyhook事件信息///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);}#endregion#regionDLLimports//////设置窗口钩子,执行所需的事件,hInstance或threadId之一必须为非空//////要挂接的事件的ID///回调。///您要将事件附加到的句柄,可以为null///您要将事件附加到的线程,可以为null///所需挂钩的句柄[DllImport("user32.dll")]staticexternIntPtrSetWindowsHookEx(intidHook,keyboardHookProc回调,IntPtrhInstance,uintthreadId);//////解除窗口挂钩。//////从SetWindowsHookEx返回的钩子句柄///如果成功则为真,否则为假[DllImport("user32.dll")]staticexternboolUnhookWindowsHookEx(IntPtrhInstance);//////调用下一个钩子。//////钩子ID///钩子代码///wparam。///参数。///[DllImport("user32.dll")]staticexternintCallNextHookEx(IntPtridHook,intnCode,intwParam,refkeyboardHookStructlParam);//////加载库。//////库的名称///l的句柄ibrary[DllImport("kernel32.dll")]staticexternIntPtrLoadLibrary(stringlpFileName);#endregion}}我用IDisposable更新了我应该做的代码,我可能会非常失望,但它仍然不起作用问题是:hhook=SetWindowsHookEx(WH_KEYBOARD_LL,hookProc,hInstance,0);只是语法糖:hhook=SetWindowsHookEx(WH_KEYBOARD_LL,newkeyboardHookProc(hookProc),hInstance,0);所以keyboardHookProc对象只是本地的,并且将被处理掉,因为SetWindowsHookEx实际上在宿主环境中没有做任何事情。要解决此问题,请在定义成员变量的顶部添加一个,如下所示:IntPtrhhook=IntPtr.ZeroprivatekeyboardHookProchookProcDelegate;然后将构造函数更改为:publicglobalKeyboardHook(){hookProcDelegate=hookProc;钩();}然后将hook()方法更改为:publicvoidhook(){IntPtrhInstance=LoadLibrary("User32");hhook=SetWindowsHookEx(WH_KEYBOARD_LL,hookProcDelegate,hInstance,0);这样你就可以使用存储作为成员变量的委托,只要你的globalKeyboardHook对象还活着,它就会活着。听起来你正在实例化一个globalKeyboardHook然后让它被垃圾收集。我猜你做的是这样的:publicvoidInstallHook(){varhook=newglobalKeyboardHook();您需要保留对globalKeyboardHook()的引用,以防止它被垃圾回收。globalKeyboardHook挂钩;publicvoidInstallHook(){hook=newglobalKeyboardHook();即使使用新代码,我仍然会收到上述错误,作为一种解决方案,我只是将委托的实例保留在类范围内,现在错误不再出现。//不要忘记声明kbhproc类varthis.kbhProc=newkeyboardHookProc(hookProc);hhook=SetWindowsHookEx(WH_KEYBOARD_LL,this.kbhProc/*newkeyboardHookProc(hookProc)*/,hInstance,0);上面的代码是基于问题代码。我想添加这个以供将来参考,因为它可能有助于理解Tim的回答,并且如果您有复杂的代码,也许还可以调试正在发生的事情:callbackOnCollectedDelegateMDAhttps://docs.microsoft.com/en-us/dotnet/framework/debug-trace-profile/callbackoncollecteddelegate-mda以上是C#学习教程:已经在C#中调用了垃圾回收委托?如果所有分享的内容对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处:
