挂钩SetConsoleCtrlHandler时没有堆栈跟踪的NullReferenceException

Oha*_*der 7 c# console hook

使用代码从这个线程挂钩控制台关闭事件,我有时得到一个NullReferenceException没有堆栈跟踪(大多数时候我没有).它发生在发布和调试中,并且"抛出异常时中断"没有帮助(它中断,但堆栈跟踪仍为空).当我正常退出我的应用程序时(我正在点击进入并因此释放a Console.ReadLine),我从未得到此异常.应用程序事件日志有2个条目:

应用程序:MyApp.exe Framework版本:v4.0.30319描述:由于未处理的异常,进程已终止.异常信息:System.NullReferenceException Stack:

和:

故障应用程序名称:Gateway.exe,版本:1.0.0.0,时间戳:0x4e284101故障模块名称:未知,版本:0.0.0.0,时间戳:0x00000000异常代码:0xc0000005故障偏移:0x004d41ce故障进程id:0xf00故障应用程序启动时间:0x01cc47b827e19a6e错误应用程序路径:C:\ dev\MyApp.exe错误模块路径:未知报告ID:689c1caa-b3ab-11e0-ba1b-00247e777f12

谷歌已经发现了一些漏洞问题SetConsoleCtrlHandler,所以我不知道这是否是一个败仗.

Han*_*ant 12

像这样的代码最典型的问题是不保留对委托实例的引用.您作为SetConsoleCtrlHandler()的第一个参数传递的那个.垃圾收集器无法通过非托管代码查看对委托对象的引用.因此,当垃圾收集器运行时,这最终会爆炸:

 SetConsoleCtrlHandler(Handler, true);
Run Code Online (Sandbox Code Playgroud)

这与完全相同

 SetConsoleCtrlHandler(new EventHandler(Handler), true);
Run Code Online (Sandbox Code Playgroud)

假设您使用了链接代码中的类型.该代码的作者通过使_handler成为静态变量来仔细避免此问题.与前两行代码创建的临时委托实例相反.将其存储在静态变量中可确保它在程序的生命周期内保持引用.在这个特殊情况下要做的事情,因为你实际上对事件感兴趣,直到程序结束.