WinForms全局exception处理?

我已经实现了一个软件,它有一个DLL库,其中包含一大堆类,其中包括我的软件的所有方法。

现在我希望能够处理一些全局错误,例如错误#26,这对所有这些类都没有网络相关错误,而不是去每个类并添加它。 怎么做 ?

如果#26是一个例外,那么您可以使用AppDomain.CurrentDomain.UnhandledException事件。 如果它只是一个返回值,那么我认为没有任何机会全局处理它。

由于它是一个winforms应用程序,你可以只包含Application.Run(new MainForm()); 在try catch块中。

 static void Main() { try { Application.Run(new MainForm()); } catch(SystemException)//just as an example { //log or handle the error here. } } 

我不知道这种解决方案会带来什么影响,但我只是告诉你你需要什么。

其他选项是订阅Application.ThreadException事件。

在这里阅读更多: unhandledexceptions

还有AppDomain.UnhandledException,您应该在MSDN上阅读它们之间的区别。

来自MSDN:

对于某些应用程序模型,如果主应用程序线程中发生未处理的exception,则UnhandledException事件可被其他事件抢占。

在使用Windows窗体的应用程序中,主应用程序线程中的未处理exception会导致引发Application.ThreadException事件。 如果处理此事件,则默认行为是未处理的exception不会终止应用程序,尽管应用程序处于未知状态。 在这种情况下,不会引发UnhandledException事件。 可以通过使用应用程序配置文件或使用Application.SetUnhandledExceptionMode方法在连接ThreadException事件处理程序之前将模式更改为UnhandledExceptionMode.ThrowException来更改此行为。 这仅适用于主应用程序线程。 针对在其他线程中引发的未处理exception引发UnhandledException事件。

在C#Windows应用程序中引用了集中式exception处理 ,我找到了一个很好的解决方案:

 static class Program { [STAThread] static void Main() { // Add handler to handle the exception raised by main threads Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException); // Add handler to handle the exception raised by additional threads AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException); Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Form1()); // Stop the application and all the threads in suspended state. Environment.Exit(-1); } static void Application_ThreadException (object sender, System.Threading.ThreadExceptionEventArgs e) {// All exceptions thrown by the main thread are handled over this method ShowExceptionDetails(e.Exception); } static void CurrentDomain_UnhandledException (object sender, UnhandledExceptionEventArgs e) {// All exceptions thrown by additional threads are handled in this method ShowExceptionDetails(e.ExceptionObject as Exception); // Suspend the current thread for now to stop the exception from throwing. Thread.CurrentThread.Suspend(); } static void ShowExceptionDetails(Exception Ex) { // Do logging of exception details MessageBox.Show(Ex.Message, Ex.TargetSite.ToString(), MessageBoxButtons.OK, MessageBoxIcon.Error); } } 

在上面的类中,我们将为两个事件附加一个事件处理程序。 主方法启动后,最好附加这些事件。

Application.ThreadException – 在主线程中抛出exception时将引发此事件。 如果我们添加一个事件处理程序,则通过该方法处理exception。

AppDomain.CurrentDomain.UnhandledException – 当在应用程序中使用的其他线程中引发exception时,将引发此事件。 这里更糟糕的情况是,一旦处理程序的执行结束,exception再次抛出,而应用程序结束。 这需要处理。 在这里,我使用了一些代码来处理这种情况,并继续执行应用程序而不会中断。

我用来克服这种情况的逻辑只是暂停事件处理程序中的线程,以便应用程序继续正常工作。 在暂停该线程时再次出现问题。 当主窗体关闭时,应用程序通常需要退出,但是当线程处于挂起状态时,应用程序仍将继续运行。 因此,要完全退出应用程序并停止进程,必须在main方法结束之前调用Environment.Exit(-1)。

处理Application.ThreadException事件。

首先,您应该添加:

 Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException); 

之后您可以捕获exception,例如:

 [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException); Application.ThreadException += ApplicationThreadException; AppDomain.CurrentDomain.UnhandledException += CurrentDomainOnUnhandledException; if (DataBaseMNG.Init()) { Application.Run(new MainForm()); } } ///  /// Global exceptions in Non User Interfarce(other thread) antipicated error ///  ///  ///  private static void CurrentDomainOnUnhandledException(object sender, UnhandledExceptionEventArgs e) { var message = String.Format( "Sorry, something went wrong.\r\n" + "{0}\r\n" + "{1}\r\n" + "please contact support.", ((Exception)e.ExceptionObject).Message, ((Exception)e.ExceptionObject).StackTrace); MessageBox.Show(message, @"Unexpected error"); } ///  /// Global exceptions in User Interfarce antipicated error ///  ///  ///  private static void ApplicationThreadException(object sender, ThreadExceptionEventArgs e) { var message = String.Format( "Sorry, something went wrong.\r\n" + "{0}\r\n" + "{1}\r\n" + "please contact support.", e.Exception.Message, e.Exception.StackTrace); MessageBox.Show(message, @"Unexpected error"); } 

winforms中的全局错误拦截

  static class Program { ///  /// The main entry point for the application. ///  [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); try { Application.Run(new myForm()); } catch (Exception ex) { HandleException(ex); } } internal static void HandleException(Exception ex) { string LF = Environment.NewLine + Environment.NewLine; string title = $"Oups... I got a crash at {DateTime.Now}"; string infos = $"Please take a screenshot of this message\n\r\n\r" + $"Message : {LF}{ex.Message}{LF}" + $"Source : {LF}{ex.Source}{LF}" + $"Stack : {LF}{ex.StackTrace}{LF}" + $"InnerException : {ex.InnerException}"; MessageBox.Show(infos, title, MessageBoxButtons.OK, MessageBoxIcon.Error); // Do logging of exception details } } 

作为上面显示的内容的扩展,我使用以下内容:

 try { Application.Run(new FormMain()); } catch (Exception ex) { RoboReporterConstsAndUtils.HandleException(ex); } 

… HandleException()方法可以是这样的:

 internal static void HandleException(Exception ex) { var exDetail = String.Format(ExceptionFormatString, ex.Message, Environment.NewLine, ex.Source, ex.StackTrace, ex.InnerException); ExceptionLoggingService.Instance.LogAndEmailExceptionData(string.Format("{0}: {1}: {2}", DateTime.Now.ToLongDateString(), GetVersionInfo(), exDetail)); } 

皮肤这种猫的另一种方法是:

 static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); AppDomain.CurrentDomain.UnhandledException += Unhandled; Application.Run(new FormMain()); } static void Unhandled(object sender, UnhandledExceptionEventArgs exArgs) { ExceptionLoggingService.Instance.LogAndEmailMessage(String.Format ("From application-wide exception handler: {0}", exArgs.ExceptionObject)); } 

当然,您可以在Unhandled()方法中执行任何操作。