.net AppDomain未捕获未处理的异常。未处理的异常

.net AppDomain未捕获未处理的异常。未处理的异常,.net,multithreading,vb6,unhandled-exception,.net,Multithreading,Vb6,Unhandled Exception,我们有一个由VB6“代理”(exe)通过COM接口执行的.NET3.5程序集(dll)。VB6代码不调用: “确保在使用GPF时不会出现系统对话框。 PreviousErrorMode=设置错误模式(SEM_Nogpfault Terrorbox) SetErrorMode先前的ERRORMODE或SEM_NOGPFAULTERRORBOX '为此进程分配我们的异常处理程序。 PreviousExceptionFilter=SetUnhandledExceptionFilter(Unhandle

我们有一个由VB6“代理”(exe)通过COM接口执行的.NET3.5程序集(dll)。VB6代码不调用:

“确保在使用GPF时不会出现系统对话框。
PreviousErrorMode=设置错误模式(SEM_Nogpfault Terrorbox)
SetErrorMode先前的ERRORMODE或SEM_NOGPFAULTERRORBOX
'为此进程分配我们的异常处理程序。
PreviousExceptionFilter=SetUnhandledExceptionFilter(UnhandledExceptionFilter的地址)
VB6
UnhandledExceptionFilter
将异常转换为VB6引发的错误。(但这里也没有调用它,而且这段VB6代码已经多年没有被更改过,甚至没有重新编译过。)

在VB6代码创建的第一个.NET对象的构造函数中,我向
AppDomain.CurrentDomain.UnhandledException
添加了一个处理程序(在尝试调试此问题时,我为
Windows.Forms.Application.ThreadException
添加了一个处理程序,但它没有帮助,因为.NET显示了任何UI)

我确信在VS2008中开发此代码时,
UnhandledException
事件捕获了一些东西,但我不确定我是否在VS2015中见过它

代码运行多个线程,其中一些线程执行主要任务,包括插入和更新SQL Server数据,以及通过TCP协议进行通信,TCP协议由其他线程处理,包括
BackgroundWorker

实现主要目的的机构通过以下方式创建:

taskThread=新线程(EnsureTaskCompletes的地址)
taskThread.SetApartmentState(Threading.ApartmentState.STA)
taskThread.Start()
它过于专有和复杂,无法向您显示更多的代码,但我在调试此问题时对代码进行了调整,只需
抛出新异常
,而不是最终产生相同效果的复杂代码。(*)

这个“简单”异常不是由
UnhandledExceptionHandler
处理的,除非我打开了非托管调试,否则它会自动终止程序

当.NET Framework“仅”作为dll加载时,
AppDomain.CurrentDomain.UnhandledException的行为是否有记录在案的更改?

(由于COM重新注册,我不想在VS2008中生成以前的版本,但要确认是否存在行为更改。我已确认VS2015编译的.NET 3.5 Exe创建了一个引发未处理异常的
线程
,并在
未处理异常
事件中处理该异常。)

我的解决方法是在
EnusreTaskCompletes
中的现有
Try Finally
中添加一个
Catch
,该线程已尝试至少记录在任务完成之前线程已终止,并调用
unhandledeExceptionHandler
我自己


(*实际的问题是数据库中缺少一个表,该表仅在信用耗尽时使用——我没有添加该代码或该表。这引发了一个异常,
UnhandledExceptionHandler
没有捕获到该异常,这使得调试变得相当困难——SQL Server Profiler最终发现了该问题。)

以极快的速度,这是一个极其广泛的话题。不,当从VB6调用代码时,您永远不会观察到未处理的异常事件。通过互操作边界传递异常是严格禁止的

CLR遵从,它在CCW中使用catch-em-all异常处理程序来捕获异常。并将其转换为符合COM的HRESULT错误代码。每个.NET异常都有一个不同的属性值

VB6运行时将它们转换为VB6错误。您需要使用
On Error
语句来捕获它们。CLR实现IErrorInfo以提供一些信息,VB6
Err.Number
属性具有Exception.HResult值,
Err.Description
为您提供Exception.Message属性值。但是,如果您需要InnerException属性来诊断灾难,您将无法获得Holy Stacktrace,并将受到严重不便。考虑使用AppDima.FrestChsExeExver事件来记录详细信息。

调试这样的异常非常容易。使用项目>属性>调试>启动外部程序单选按钮。选择编译的VB6程序或VB6 IDE。在VS2015中,使用调试>窗口>异常设置并勾选“公共语言运行时异常”,强制调试器在第一次出现异常时停止

请注意,此机制对于在自己的工作线程上运行的任何代码都无效。在互操作场景中处理这些问题是非常棘手的。大概这就是让你对“有时它会起作用”情景感到困惑的原因

请务必小心使用SetUnhandledExceptionFilter(),这很容易破坏.NET代码。CLR也调用该函数来安装自己的处理程序,并使用它引发一些异常。值得注意的是NullReferenceException和DivideByZeroException,这类异常是C#代码可能希望自己捕获的。还有一些非常糟糕的东西,比如AccessViolationException,你永远都不想抓住它。它还可能会干扰VB6错误。顺便说一句,运行时还使用SEH引发异常。

(这只是一个注释,特别是因为它主要是将我的注释扩展到描述新问题的问题,但它变得太大了。)

我至少在所有版本中(即使在重置了Visual Studio设置等之后*)都出现了我所看到的问题,在“模块加载时抑制JIT优化(仅管理)”关闭且“仅我的代码”打开的发布版本中,我使用了普通的.NET控制台应用程序。显然,这几乎是一个完全非调试运行,并且它在这里警告不会命中断点,因为符号尚未加载

(事实上,我只是后来才注意到这个故障记录在