我之前在程序的入口点 Program.cs
中,只是将 try/catch 块放在了 Application.Run
方法的周围。这样在调试模式下可以很好地捕获所有异常,但是当我在非调试模式下运行程序时,异常就不再被处理了。我会看到未处理异常的对话框。
我不想让这种情况发生。我希望无论在何种模式下运行程序,都能够捕获所有异常。程序中有多个线程,最好能够通过同一个处理程序来捕获所有线程的异常;我希望将异常记录在数据库中。请问有什么建议吗?
我之前在程序的入口点 Program.cs
中,只是将 try/catch 块放在了 Application.Run
方法的周围。这样在调试模式下可以很好地捕获所有异常,但是当我在非调试模式下运行程序时,异常就不再被处理了。我会看到未处理异常的对话框。
我不想让这种情况发生。我希望无论在何种模式下运行程序,都能够捕获所有异常。程序中有多个线程,最好能够通过同一个处理程序来捕获所有线程的异常;我希望将异常记录在数据库中。请问有什么建议吗?
看一下来自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);
}
在调试时,您可能还想避免捕获异常,因为这样可以更轻松地进行调试。这有点像是一种hack操作,但您可以使用以下代码将其包装起来:
if (!AppDomain.CurrentDomain.FriendlyName.EndsWith("vshost.exe")) { ... }
为了在调试时避免捕获异常。
编辑:一种替代方法,用于检查应用程序是否在调试器中运行,该方法比检查文件名更简洁。
(参见moltenform、Kiquenet和Doug的评论)
if(!System.Diagnostics.Debugger.IsAttached) { ... }
这样做避免了使用与 vshost.exe
不同的调试器所带来的问题。
Debugger.IsAttached
来 防止在调试时捕获异常 和 _即使处理了 UnhandledException,应用程序也仍然会终止_(参考 by @NazarGrynko) - Kiquenetusing 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;
}
[HandleProcessCorruptedStateExceptions]
标记下同时使用AppDomain.CurrentDomain.UnhandledException
和Application.ThreadException
吗? - Kiquenet一个好的例子可以在http://www.csharp-examples.net/catching-unhandled-exceptions/找到。 基本上,将您的主要函数更改为:
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");
}
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());
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
也没有改变任何东西。 - gideon