Вы можете захватывать незапланированные (и потоковые) исключения, используя свойства Application.ThreadException и AppDomain.CurrentDomain.UnhandledException.
Ваш Main будет выглядеть примерно так:
[STAThread]
static void Main() {
if (Debugger.IsAttached) {
Run();
return;
}
Application.ThreadException += ApplicationThreadException;
AppDomain.CurrentDomain.UnhandledException += CurrentDomainUnhandledException;
Run();
}
Обратите внимание на проверку отладчика, чтобы отладчик мог перехватывать эти исключения при разработке.
Функция Run довольно проста
static void Run() {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm());
}
А затем два обработчика исключений.
static void ApplicationThreadException(object sender, ThreadExceptionEventArgs e) {
ErrorInformationDialog eid = new ErrorInformationDialog(e.Exception.Message, e.Exception);
eid.ShowDialog();
}
static void CurrentDomainUnhandledException(object sender, UnhandledExceptionEventArgs e) {
ErrorInformationDialog eid = new ErrorInformationDialog(e.ExceptionObject as Exception);
eid.ShowDialog();
}
А ErrorInformationDialog - это просто форма, которую я собрал, чтобы отобразить уведомление об ошибке и дать инструкции по ее уведомлению.