WinForms如何能够静默地忽略未处理的异常? [英] How can I get WinForms to stop silently ignoring unhandled exceptions?

查看:116
本文介绍了WinForms如何能够静默地忽略未处理的异常?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是非常刺激的。现在我有一个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 main方法和添加 Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException); 。仍然是我的表单加载而不会导致任何错误被抛出。



即使我知道我可以告诉VS打破所有异常,我发现这种情况真的很糟糕。它会导致在生产中难以调试的真正问题,因为这是一个内部工具,我真的想拥有它,所以当异常发生时实际上会出错,而不是默默地忽略它。



有没有人知道如何做?





更新:只是为了更新从评论中学到的东西。



这似乎是Windows的64位问题,我从这个问题我在发布之前看不到。在该问题中,它指出了 Microsoft错误报告,这有说:


您好,



这个错误被关闭为外部,因为这种行为是由x64版本的Windows处理异常引起的。当用户模式异常跨越内核转换时,x64版本的Windows不允许异常传播。因此,附加的调试器不知道发生异常的事实导致调试器无法中断未处理的异常。



不幸的是,Visual Studo团队可以做什么为了解决这个问题,这是操作系统设计的结果。关于这个问题的所有反馈都应该发送给Windows团队;然而,Windows团队认为这是正确的操作系统设计,并认为x86行为是不正确的。



最好的问候,
视觉Studio Debugger


据说,构建不通过visual studio(或使用Ctrl + F5运行)运行似乎显示了JIT如果您的 Program.cs 中有以下代码:

  Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException); 

该代码将导致窗口忽略异常。



但是,如果你(而是)订阅了 Application.ThreadException 事件,不仅会捕获你的异常,visual studio的调试器将会打破未处理的异常!

解决方案

在你的Program.cs的主要功能中,你还应该确保你打包了你的电话在try / catch中打开表单。另外使用 AppDomain.UnhandledException 捕获异常。我们还添加了 Application.ThreadException



我相信以下将给你挂钩所有的异常,被抛出...

  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(异常e)
{
HandleUnhandledException(e);
}
finally
{
//做东西
}
}

private static void HandleUnhandledException(Object o)
{
// TODO:登录!
异常e = o为异常;

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);
}


This is getting extremely irritating. Right now I have a winforms application, and things were not working right, but no exceptions were being thrown as far as I could tell. After stepping through almost all pieces of relevant code, it turns out that an exception was being thrown at the start of my application.

Long story short, in WinForms, being as awesome as it is, if an exception occurs the WinForms library ignores it. No "an unhandled exception has occurred" JIT message is thrown, it just stops processing the current event and goes back to the GUI.

This is causing random bugs, because code to load data isn't being called due to the exception occurring prior to this data being loaded.

To see this in action I created a brand new WinForms application, and entered the following code:

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

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

Press F5 and the form loads without any errors showing, even though a null reference is being thrown.

I then tried to go to my Program.cs main method and add Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException); to it. Still my form loads without causing any errors to be thrown.

Even though I know that I can tell VS to break on all exceptions, I find this situation really bad. It causes really wierd issues that are hard to debug in production, and as this is an internal tool I really want to have it so it actually errors out when an exception occurs, and not silently disregards it.

Does anyone know how to do this?


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

This does appear to be a 64-bit issue with windows, as I learned from this question which I did not see before posting. In that question it pointed to a Microsoft bug report about this, which had this to say:

Hello,

This bug was closed as "External" because this behavior results from how x64 version of Windows handle exceptions. When a user mode exception crosses a kernel transition, x64 versions of Windows do not allow the exception to propagate. Therefore attached debuggers are unaware of the fact that an exception occured resulting in the debugger failing to break on the unhandled exception.

Unfortunately where is nothing that the Visual Studo team can do to address this, it is the result of operating system design. All feedback regarding this issue should be addressed to the Windows team; however the Windows team considers this to be the "correct" operating system design, and considers the x86 behavior to be "incorrect".

Best Regards, Visual Studio Debugger

That being said, builds not run through visual studio (or using Ctrl+F5 to run) does seem to show the JIT exception message box EXCEPT if you have the following code in your Program.cs:

Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException);

That code will cause windows to ignore the exception.

However, if you (instead) subscribe to the Application.ThreadException event, not only will your exceptions be caught, visual studio's debugger will break on unhandled exceptions!

解决方案

In your Program.cs' Main function you should also ensure that you've wrapped your call to open the form in a try/catch. Additionally use the AppDomain.UnhandledException to catch exceptions. We also add Application.ThreadException too.

I believe the following will give you hooks into all the exceptions that can be thrown...

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);
}

这篇关于WinForms如何能够静默地忽略未处理的异常?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆