如何使用简历实现一个“catch'em all”异常处理程序?

时间:2008-12-03 16:15:56

标签: c# exception

我想知道如何在应用程序级别编写 catch'em所有 异常处理程序,这将为用户提供恢复应用程序流的选项?

9 个答案:

答案 0 :(得分:33)

如果您正在运行Windows窗体应用程序:为Application.ThreadException事件添加处理程序。

答案 1 :(得分:32)

我假设您正在编写Windows应用程序,在这种情况下,,您可以执行此操作。我将把你是否应该对别人的权利和错误留下来。已经有足够多的答案来看待这一点,我建议你在实际执行此操作之前仔细考虑

请注意,此代码在调试器中的行为与直接运行应用程序时的行为不同(另一个原因可能不是这样做)。要让应用程序显示消息框并在此后继续,您需要从资源管理器运行应用程序,而不是从visual studio运行。

创建一个新的Windows窗体应用程序。 Program.cs中的代码如下所示:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Windows.Forms;

namespace WindowsFormsApplication2 {
    static class Program {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main() {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Form1 form1 = new Form1();
            Application.ThreadException += new ThreadExceptionEventHandler(form1.UnhandledThreadExceptionHandler);
            Application.Run(form1);
        }
    }
}

然后使Form1中的代码看起来像这样:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;

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

        public void UnhandledThreadExceptionHandler(object sender, ThreadExceptionEventArgs e) {
            this.HandleUnhandledException(e.Exception);
        }

        public void HandleUnhandledException(Exception e) {
            // do what you want here.
            if (MessageBox.Show("An unexpected error has occurred. Continue?",
                "My application", MessageBoxButtons.YesNo, MessageBoxIcon.Stop,
                MessageBoxDefaultButton.Button2) == DialogResult.No) {
                Application.Exit();
            }
        }

        private void button1_Click(object sender, EventArgs e) {
            throw new ApplicationException("Exception");
        }

    }
}

(将button1添加到表单并将其附加到button1_Click。)

答案 2 :(得分:19)

这取决于“简历”的含义。异常的问题在于,除非您非常非常小心,否则当异常发生时,您的应用程序状态很可能已损坏 - 您可能已完成一半操作。< / p>

如果您可以隔离您的操作 - 就像数据库隔离事务一样 - 那么您可以有效地让您的用户从“最后一个提交点”恢复。这在很大程度上取决于您的应用程序的类型。您能否提供有关您正在构建的应用程序类型的更多详细信息?

答案 3 :(得分:6)

在program.cs类中使用以下代码。它会在发生异常时自动发送邮件。

using System;
using System.Windows.Forms;
using System.Net;
using System.Net.Mail;
using System.Threading; 

namespace ExceptionHandlerTest
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.ThreadException +=
                new ThreadExceptionEventHandler(Application_ThreadException);

            // Your designer generated commands.
        }

        static void Application_ThreadException(object sender, ThreadExceptionEventArgs e) 
        {

            var fromAddress = new MailAddress("your Gmail address", "Your name");
            var toAddress = new MailAddress("email address where you want to receive reports", "Your name");
            const string fromPassword = "your password";
            const string subject = "exception report";
            Exception exception = e.Exception;
            string body = exception.Message + "\n" + exception.Data + "\n" + exception.StackTrace + "\n" + exception.Source;

            var smtp = new SmtpClient
            {
                Host = "smtp.gmail.com",
                Port = 587,
                EnableSsl = true,
                DeliveryMethod = SmtpDeliveryMethod.Network,
                UseDefaultCredentials = false,
                Credentials = new NetworkCredential(fromAddress.Address, fromPassword)
            };
            using (var message = new MailMessage(fromAddress, toAddress)
            {
                Subject = subject,
                Body = body
            })
            {
                //You can also use SendAsync method instead of Send so your application begin invoking instead of waiting for send mail to complete. SendAsync(MailMessage, Object) :- Sends the specified e-mail message to an SMTP server for delivery. This method does not block the calling thread and allows the caller to pass an object to the method that is invoked when the operation completes. 
                smtp.Send(message);
            }
        }
    }
}

答案 4 :(得分:4)

我认为使用全局错误处理程序并不可行。您需要弄清楚在应用程序的不同位置可以恢复哪些类型的错误,并编写特定的错误处理程序来解决发生的错误 - 除非您想要求助于重新启动应用程序,这可能会或可能不会起作用,具体取决于实际错误是。为了执行任何类型的恢复,您需要保存足够的状态以从已知良好状态重新启动。

答案 5 :(得分:-1)

在某些版本的.NET中,您实际上可以在Application.Run()周围放置一个捕手(您可以在program.cs中找到它),这应该可以捕获所有主线程的异常但是在大多数情况下这可能是糟糕的设计并且不会给你很多“恢复”的机会。 此外,总是必须手动处理后台线程上的任何异常。

您可以将应用程序设计为“全部捕获”并显示常见错误消息和调试信息,只要您以后退出就可以了。非常气馁的是为用户提供“简历”,因为从长远来看,这可能会给你带来更多问题。

答案 6 :(得分:-1)

您应该阅读与VB的“On Error Resume Next”错误处理方式相关的所有问题。听起来你正试图为C#实现这个。

即使您可以从生成异常的位置恢复,这也是一种错误处理错误的技术。全局处理程序无法实际处理任何错误/异常 - 它无法知道任何情况下所需的内容。

您必须设置某种全局变量,并让主线代码不断检查它是否有错误指示(即,使用VB技术)。

我认为从您正在描述的错误中恢复的最佳方法是在应用程序级别捕获异常,记录问题,通知用户(并可能为您生成/发送某种问题报告) ),并重新启动应用程序。当然,如果您在问题区域附近发现异常,那么该处理程序有机会做一些更聪明的事情,因此您不应该依赖应用程序级别的处理程序作为拐杖 - 就像故障安全一样。 / p>

答案 7 :(得分:-2)

这只是尖叫着糟糕的设计。永远不要对这样的事情使用例外。只有在程序员不打算发生的事情时才会使用例外。

如果您想要错误处理。不要使用这样的例外,rahter构建一个系统,你可以保存状态,然后可以返回状态等......但是使用异常进行状态处理,不好主意。

答案 8 :(得分:-3)

Microsoft Enterprise Library Exception Handling Application Block举例说明了如何做到这一点。

基本上,您可以使用以下方法包围可能引发异常的代码:

try
{
  MyMethodThatMightThrow();
}
catch(Exception ex)
{
   bool rethrow = ExceptionPolicy.HandleException(ex, "SomePolicy");
   if (rethrow) throw;
}

然后,您可以配置策略以向用户显示对话框,并询问她是否要继续。

您仍然需要在您认为自己处于一致状态的位置放置try catch块。