如何让 WinForms 停止默默地忽略未处理的异常?

2024-01-12

这变得非常令人恼火。现在我有一个 winforms 应用程序,事情运行不正常,但据我所知,没有抛出任何异常。在单步执行几乎所有相关代码后,结果发现在我的应用程序启动时抛出了异常。

长话短说,在 WinForms 中,虽然它本身很棒,但如果发生异常,WinForms 库会忽略它。不会抛出“发生未处理的异常”JIT 消息,它只是停止处理当前事件并返回到 GUI。

这会导致随机错误,因为由于加载数据之前发生异常,因此未调用加载数据的代码。

为了查看其实际效果,我创建了一个全新的 WinForms 应用程序,并输入了以下代码:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        string blah = null;
        blah.Trim();
    }
}

按 F5 即可加载表单,即使抛出空引用,也不会显示任何错误。

然后我尝试去我的Program.cs主要方法并添加Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException);到它。我的表单仍然加载,没有引发任何错误。

尽管我知道我可以告诉 VS 在所有异常上中断,但我发现这种情况非常糟糕。它会导致非常奇怪的问题,在生产中很难调试,而且由于这是一个内部工具,我真的很想拥有它,因此当异常发生时它实际上会出错,而不是默默地忽略它。

有谁知道如何做到这一点?


Update: Just to update on things I have learned from the comments.

据我了解,这似乎是 Windows 的 64 位问题这个问题 https://stackoverflow.com/questions/4933958/vs2010-does-not-show-unhandled-exception-message-in-a-64-bit-winforms-application我在发布之前没有看到。在那个问题中它指出了一个微软错误报告 https://connect.microsoft.com/VisualStudio/feedback/details/357311/silent-exceptions-on-x64-development-machines关于这一点,其中有这样一句话:

Hello,

此错误已作为“外部”关闭,因为此行为是由 x64 版本的 Windows 处理异常的方式导致的。当用户模式异常跨越内核转换时,x64 版本的 Windows 不允许异常传播。因此,附加的调试器不知道发生了异常,导致调试器无法在未处理的异常上中断。

不幸的是,Visual Studo 团队无法解决这个问题,这是操作系统设计的结果。有关此问题的所有反馈均应发送给 Windows 团队;然而,Windows 团队认为这是“正确的”操作系统设计,并认为 x86 行为是“不正确的”。

此致, Visual Studio 调试器

话虽如此,未通过 Visual Studio 运行的构建(或使用 Ctrl+F5 运行)似乎确实显示了 JIT 异常消息框EXCEPT如果你的程序中有以下代码Program.cs:

Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException);

该代码将导致 Windows 忽略该异常。

但是,如果您(相反)订阅了Application.ThreadException事件,不仅会捕获你的异常,Visual Studio 的调试器will中断未处理的异常!


在 Program.cs 的 Main 函数中,您还应该确保已将打开表单的调用包装在 try/catch 中。另外使用AppDomain.UnhandledException捕获异常。我们还添加Application.ThreadException too.

我相信下面的内容会让您了解所有可能抛出的异常......

static void Main()
{
    try
    {
        System.Windows.Forms.Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
        System.Windows.Forms.Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(OnGuiUnhandedException);
        AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;

        var form = new MainForm();
        form.ShowDialog();
    }
    catch (Exception e)
    {
        HandleUnhandledException(e);
    }
    finally
    {
        // Do stuff
    }
}

private static void HandleUnhandledException(Object o)
{
    // TODO: Log it!
    Exception e = o as Exception;

    if (e != null)
    {

    }
}

private static void OnUnhandledException(Object sender, UnhandledExceptionEventArgs e)
{
    HandleUnhandledException(e.ExceptionObject);
}

private static void OnGuiUnhandedException(object sender, System.Threading.ThreadExceptionEventArgs e)
{
    HandleUnhandledException(e.Exception);
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何让 WinForms 停止默默地忽略未处理的异常? 的相关文章

随机推荐