如何制作可捕获WinForms应用程序中所有“未处理”异常的东西?


84

到目前为止,我只是Application.RunProgram.cs该程序的入口点周围放置了一个try / catch块。这样可以在调试模式下很好地捕获所有异常,但是当我在没有调试模式的情况下运行程序时,不再处理异常。我得到了未处理的异常框。

我不希望这种情况发生。我希望在非调试模式下运行时捕获所有异常。该程序有多个线程,最好所有线程中的所有异常都由同一处理程序捕获;我想在数据库中记录异常。有人对如何执行此操作有任何建议吗?

Answers:


110

看一下ThreadException文档中的示例:

public static void Main(string[] args)
{
   // Add the event handler for handling UI thread exceptions to the event.
    Application.ThreadException += new     
  ThreadExceptionEventHandler(ErrorHandlerForm.Form1_UIThreadException);

  // Set the unhandled exception mode to force all Windows Forms errors
  // to go through our handler.
  Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);

  // Add the event handler for handling non-UI thread exceptions to the event. 
  AppDomain.CurrentDomain.UnhandledException += new       
  UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
}

您可能还希望在调试时不捕获异常,因为这使调试更加容易。这有点骇人听闻,但为此您可以使用

 if (!AppDomain.CurrentDomain.FriendlyName.EndsWith("vshost.exe")) { ... }

为了防止在调试时捕获异常。


1
我做了一个后台工作人员,并且在dowork事件处理程序中实际上引起了null引用异常。但是,尽管进行了以下设置,但并没有被AppDomain.CurrentDomain.UnhandledException捕获:Application.ThreadException + = new System.Threading.ThreadExceptionEventHandler(Application_ThreadException); Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException); AppDomain.CurrentDomain.UnhandledException + =新的UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
艾萨克·伯林格

4
@IsaacB,后台工作者自己捕获异常。您甚至可以在RunWorkerCompleted中查看RunCompletedEventArgs.Error属性来检查异常。
Can Gencer

1
通过将其放入主窗体的OnLoad中,可以测试其他线程的异常处理。new Thread(()=> {throw new Exception();})。Start();
Can Gencer

不幸的是,处理UnhandledException不会停止应用终止:(
Nazar Grynko 2013年

7
尝试使用更干净的Debugger.IsAttached,而不是FriendlyName.EndsWith hack。
–molentform

27

在NET 4中,默认情况下不再捕获某些异常这些往往是表示可执行文件的状态(可能是致命的)的异常,例如AccessViolationException。

尝试在主要方法前面使用[HandleProcessCorruptedStateExceptions]标签,例如

using System.Runtime.ExceptionServices.HandleProcessCorruptedStateExceptions

[HandleProcessCorruptedStateExceptions]
public static int Main()
{
    try
    {
        // Catch any exceptions leaking out of the program
        CallMainProgramLoop();
    }
    catch (Exception e) // We could be catching anything here
    {
        System.Console.WriteLine(e.Message);
        return 1;
    }
    return 0;
  } 

我可以使用AppDomain.CurrentDomain.UnhandledException,并Application.ThreadException也用[HandleProcessCorruptedStateExceptions]标签?
Kiquenet '17

18

一个很好的例子可以在http://www.csharp-examples.net/catching-unhandled-exceptions/上找到 基本上,将main更改为:

static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);

        Application.ThreadException += new ThreadExceptionEventHandler(Application_ThreadException);
        Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
        AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

        Application.Run(new Form1());
    }

    static void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
    {
        MessageBox.Show(e.Exception.Message, "Unhandled Thread Exception");
    }

    static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
    {
        MessageBox.Show((e.ExceptionObject as Exception).Message, "Unhandled UI Exception");
    }

9

您可以使用NBug库。像这样的最小设置:

NBug.Settings.Destination1 = "Type=Mail;From=me@mycompany.com;To=bugtracker@mycompany.com;SmtpServer=smtp.mycompany.com;";
AppDomain.CurrentDomain.UnhandledException += NBug.Handler.UnhandledException;
Application.ThreadException += NBug.Handler.ThreadException;

您可以开始收集有关应用程序中所有未处理错误的信息,即使已将其部署到客户端也是如此。如果您不想使用第三方库,则应附加以下事件:

// These two should come before enabling visual styles or running the application
AppDomain.CurrentDomain.UnhandledException += ...
Application.ThreadException += ...
...
Application.Run(new Form1());

1
别客气。如果您还有其他问题(nbusy.com/forum/f11),请使用NBug项目讨论论坛,或在此处使用[nbug]标记。
Teoman Soygul 2011年

当然,您也可以为UnhandledException事件订阅一个“常规”事件处理程序。见msdn.microsoft.com/en-us/library/...
neo2862

在Win7 + VS10上,如果我订阅这些事件,则订阅不会运行,而是显示常规Windows Vista / 7对话框Check Online for a SolutionClose the Program..等。但是,如果我不订阅,则会收到常规的通用.NET未处理异常窗口。在发布版本和调试版本中都会发生这种情况,也尝试设置Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);“不更改任何内容”。
gideon 2011年

@giddy,处理异常后,应使用Environment.Exit(1);退出应用程序。如果您不希望显示错误窗口。
Teoman Soygul 2011年

@Teo感谢您的回复。我希望显示自己的错误表单,然后退出该应用程序。但是事件订阅永远不会运行,当它遇到异常时它只会显示通用的Win Vista / 7对话框。但是,如果我不订阅,就会出现通用.NET未处理的异常对话框!
gideon 2011年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.