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