gpt4 book ai didi

.net - AppDomain.UnhandledException 未捕获未处理的异常

转载 作者:行者123 更新时间:2023-12-04 16:45:53 29 4
gpt4 key购买 nike

我们有一个 .NET 3.5 程序集 (dll),由 VB6“代理”(exe) 通过 COM 接口(interface)执行。 VB6 代码调用:

' Ensure that no system dialog comes up when we GPF.
PreviousErrorMode = SetErrorMode(SEM_NOGPFAULTERRORBOX)
SetErrorMode PreviousErrorMode Or SEM_NOGPFAULTERRORBOX

' Assign our Exception Handler for this process.
PreviousExceptionFilter = SetUnhandledExceptionFilter(AddressOf UnhandledExceptionFilter)

并且 VB6 UnhandledExceptionFilter 将异常转换为 VB6 引发的错误。 (但这里也没有调用它,而且这段 VB6 代码多年来一直没有更改——甚至没有重新编译。)

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

我确定在 VS2008 中开发这段代码时 UnhandledException 事件已经捕获了一些东西,但我不确定我是否在 VS2015 中看到过它。

代码正在运行多个线程,其中一些正在执行主要目的,包括插入和更新 SQL Server 数据,还通过 TCP 协议(protocol)进行通信,由其他线程处理,包括 BackgroundWorker.

那些执行主要目的的人是通过以下方式创建的:

taskThread = New Thread(AddressOf EnsureTaskCompletes)
taskThread.SetApartmentState(Threading.ApartmentState.STA)
taskThread.Start()

它太专有且复杂,无法向您展示更多代码,但我在调试此问题时调整了代码以简单地 Throw New Exception 而不是最终具有相同效果的复杂代码.(*)

这个“简单”的异常没有被 UnhandledExceptionHandler 处理,除非我打开了非托管调试,否则它会静静地终止程序。

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

(由于 COM 重新注册,我不想在 VS2008 中构建以前的版本以确认行为更改。我已经确认了一个 . NET 3.5 Exe 由 VS2015 编译创建一个 Thread 抛出未处理的异常 does 处理 UnhandledException 中的异常事件。)

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

(*实际问题是数据库中缺少一个表,该表仅在您用完信用时使用——我没有添加该代码或表。这引发了一个未被UnhandledExceptionHandler,使得调试变得相当困难——SQL Server Profiler 终于找到了问题。)

最佳答案

这是一个难以置信的广泛主题,速度惊人。不,当从 VB6 调用代码时,您永远不会观察到 UnhandledException 事件。跨互操作边界传递异常是严格禁止的。

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

VB6 运行时依次将它们转换为 VB6 错误。您需要使用 On Error 语句来捕获它们。 CLR 实现 IErrorInfo 以提供一些信息,VB6 Err.Number 属性具有 Exception.HResult 值,Err.Description 为您提供Exception.Message 属性值。但是,您将不会获得 Holy Stacktrace,如果您需要 InnerException 属性来诊断故障,将会给您带来严重的不便。考虑使用 AppDomain.FirstChanceException 事件来记录详细信息。

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

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

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

关于.net - AppDomain.UnhandledException 未捕获未处理的异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39900390/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com