我的.net应用程序通过订阅AppDomain.Current.Domain UnhandledException事件而拥有一个全局异常处理程序。在几个场合,我看到我的应用程序崩溃,但这个全局异常处理程序永远不会受到攻击。不确定它的帮助,但应用程序正在做一些COM互操作。
我的理解是,只要我没有任何本地catch块吞噬异常,就应该始终触发这个全局异常处理程序。关于我可能遗失的任何想法从未被调用过吗?
答案 0 :(得分:3)
答案 1 :(得分:1)
CLR并不是全能的,可以捕获非托管代码可能导致的每个异常。通常是一个AccessViolationException btw。它只能在从托管代码调用非托管代码时捕获它们。不支持的方案是非托管代码启动自己的线程,这个线程导致崩溃。使用COM组件时非常不可能。
自.NET 4.0起,致命执行引擎异常不再导致UnhandledException事件触发。该异常被认为太难以允许运行任何更多的托管代码。它是。传统上,StackOverflowException会导致立即中止。
您可以从流程的ExitCode中稍微诊断一下。它包含终止进程的异常的异常代码。 0x8013yyyy是托管代码导致的异常。 0xc0000005是访问冲突。等等。您可以使用从Windows调试工具下载中获得的adplus来捕获该进程的小型转储。由于这可能是由COM组件引起的,因此与供应商合作可能对解决此问题非常重要。
答案 2 :(得分:1)
由于您正在进行COM互操作,我强烈怀疑某些非托管代码在另一个导致未处理异常的线程中运行。这将导致应用程序退出而不调用未处理的异常处理程序。 除了.NET 4.0之外,当应用程序关闭时,该策略确实变得更强,而不另行通知。 在下列情况下,您的应用程序将被关闭,恕不另行通知(Environmnt.FailFast)。
Pre .NET 4:
.NET 4:
您可以通过使用HandleProcessCorruptedStateExceptionsAttribute修饰方法来覆盖.NET 4中的行为,也可以将legacyCorruptedStateExceptionsPolicy标记添加到App.config中。
如果您的问题是非托管代码中的未捕获异常,您可以在调试器下运行应用程序,也可以让它崩溃并收集内存转储以进行事后调试。通常使用WindDbg来调试崩溃转储。 下载Windbg后,您有adplus(位于Programm Files \ Debugging Tools for Windows下的vbs脚本),您可以将其附加到正在运行的进程,以便在进程因异常而终止时触发崩溃转储。
adplus -crash -p yourprocessid
然后你有更好的机会找出你的进程终止时发生了什么。 Windows也可以配置为在较旧的Windows版本上通过DrWatson为您进行故障转储(Windows错误报告)
硬核程序员将坚持创建自己的转储生成工具,它基本上使用AEDebug注册表项。当该键具有指向现有可执行文件的值时,将在应用程序崩溃时调用该值,例如,显示Visual Studio调试器选择器对话框,或者它可以触发您的进程的转储生成。
一个经常被忽视的事情是当你使用外部工具创建一个崩溃转储时(最好依赖外部工具,因为你不知道你的进程有多糟糕,而且如果内存已经坏了,你已经处于糟糕状态在进行转储之前,您应该从崩溃的进程中挂起所有线程。 当你进行大量的全内存转储时,可能需要几分钟,具体取决于故障进程的已分配内存。在此期间,应用程序线程可以继续对您的应用程序状态造成严重破坏,从而使您获得一个转储,其中包含在转储生成期间发生更改的不一致的进程状态。
答案 3 :(得分:0)
如果您的处理程序抛出异常,就会发生这种情况。
如果您致电Environment.FailFast
或者Abort
用户界面线程,也会发生这种情况。