Como posso fazer algo que captura todas as exceções ‘não tratadas’ em um aplicativo WinForms?

Até agora, apenas coloquei um bloco try / catch em torno do Application.Run no ponto de input Program.cs para o programa. Isso captura todas as exceções bem o suficiente no modo de debugging, mas quando eu executo o programa sem o modo de debugging, as exceções não são tratadas mais. Eu recebo a checkbox de exceção não tratada.

Eu não quero que isso aconteça. Eu quero que todas as exceções sejam capturadas durante a execução no modo não-debugging. O programa tem vários encadeamentos e, de preferência, todas as exceções deles são capturados pelo mesmo manipulador; Eu quero registrar exceções no database. Alguém tem algum conselho sobre como fazer isso?

Dê uma olhada no exemplo da documentação do 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); } 

Você também pode querer não capturar exceções ao depurar, pois isso facilita a debugging. É um pouco de um hack, mas para isso você pode envolver o código acima com

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

Para evitar detectar as exceções ao depurar.

No NET 4, certas exceções não são mais detectadas por padrão; elas tendem a ser exceções que indicam um estado corrompido (possivelmente fatal) do executável, como uma AccessViolationException.

Tente usar a tag [HandleProcessCorruptedStateExceptions] na frente do seu método principal, por exemplo

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

Você pode usar a biblioteca NBug para isso. Com configuração mínima como esta:

 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; 

Você pode começar a coletar informações sobre todos os erros não tratados em seu aplicativo, mesmo quando ele estiver implantado nos clientes. Se você não quiser usar uma biblioteca de terceiros, deve append aos events abaixo:

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

Um bom exemplo pode ser encontrado em http://www.csharp-examples.net/catching-unhandled-exceptions/ Basicamente, mude seu principal para:

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