Как сделать что-то, что перехватывает все "необработанные" исключения в приложении WinForms?
До сих пор я просто помещал блок try/catch вокруг Application.Run
в Program.cs
точка входа в программу. Это ловит все исключения достаточно хорошо в режиме отладки, но когда я запускаю программу без режима отладки, исключения больше не обрабатываются. Я получаю необработанное исключение.
Я не хочу, чтобы это случилось. Я хочу, чтобы все исключения были перехвачены при работе в режиме без отладки. Программа имеет несколько потоков, и желательно, чтобы все исключения из них перехватывались одним и тем же обработчиком; Я хочу регистрировать исключения в БД. У кого-нибудь есть советы, как это сделать?
4 ответа
Взгляните на пример из документации 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")) { ... }
Для предотвращения отлова исключений при отладке.
В 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;
}
Хороший пример можно найти по адресу 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 для этого. С минимальной настройкой, как это:
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());