.NET Controlador global de excepciones en la aplicación de la consola

Pregunta: Quiero definir un controlador de excepción global para las excepciones no controladas en mi aplicación de consola. En asp.net, uno puede definir uno en global.asax, y en las aplicaciones / servicios de Windows, uno puede definir lo siguiente

AppDomain currentDomain = AppDomain.CurrentDomain; currentDomain.UnhandledException += new UnhandledExceptionEventHandler(MyExceptionHandler); 

Pero, ¿cómo puedo definir un manejador de excepción global para una aplicación de consola?
currentDomain parece no funcionar (.NET 2.0)?

Editar:

Argh, error estúpido.
En VB.NET, se necesita agregar la palabra clave “AddHandler” al frente de currentDomain, o si no, no se ve el evento UnhandledException en IntelliSense …
Eso es porque los comstackdores VB.NET y C # tratan el manejo de eventos de manera diferente.

No, esa es la forma correcta de hacerlo. Esto funcionó exactamente como debería, algo de lo que puedes trabajar quizás:

 using System; class Program { static void Main(string[] args) { System.AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionTrapper; throw new Exception("Kaboom"); } static void UnhandledExceptionTrapper(object sender, UnhandledExceptionEventArgs e) { Console.WriteLine(e.ExceptionObject.ToString()); Console.WriteLine("Press Enter to continue"); Console.ReadLine(); Environment.Exit(1); } } 

Tenga en cuenta que no puede detectar las excepciones de carga de archivos y tipos generadas por el jitter de esta manera. Ocurren antes de que su método Main () comience a ejecutarse. Atraparlos requiere retrasar el jitter, mover el código arriesgado a otro método y aplicarle el atributo [MethodImpl (MethodImplOptions.NoInlining)].

Si tiene una aplicación de subproceso único, puede usar un simple try / catch en la función Main; sin embargo, esto no cubre las excepciones que pueden producirse fuera de la función Main, en otros subprocesos, por ejemplo (como se indica en otra comentarios). Este código demuestra cómo una excepción puede causar que la aplicación finalice aunque haya tratado de manejarla en Main (observe cómo el progtwig sale con gracia si presiona enter y permite que la aplicación salga con gracia antes de que se produzca la excepción, pero si la deja ejecutar , termina muy infelizmente):

 static bool exiting = false; static void Main(string[] args) { try { System.Threading.Thread demo = new System.Threading.Thread(DemoThread); demo.Start(); Console.ReadLine(); exiting = true; } catch (Exception ex) { Console.WriteLine("Caught an exception"); } } static void DemoThread() { for(int i = 5; i >= 0; i--) { Console.Write("24/{0} =", i); Console.Out.Flush(); Console.WriteLine("{0}", 24 / i); System.Threading.Thread.Sleep(1000); if (exiting) return; } } 

Puede recibir una notificación de cuándo otro hilo arroja una excepción para realizar una limpieza antes de que la aplicación finalice, pero por lo que yo sé, no puede, desde una aplicación de consola, forzar que la aplicación continúe ejecutándose si no maneja la excepción en el hilo desde el que se lanza sin utilizar algunas opciones de compatibilidad poco claras para hacer que la aplicación se comporte como lo haría con .NET 1.x. Este código demuestra cómo se puede notificar al hilo principal de las excepciones provenientes de otros hilos, pero aún así terminará tristemente:

 static bool exiting = false; static void Main(string[] args) { try { System.Threading.Thread demo = new System.Threading.Thread(DemoThread); AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException); demo.Start(); Console.ReadLine(); exiting = true; } catch (Exception ex) { Console.WriteLine("Caught an exception"); } } static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) { Console.WriteLine("Notified of a thread exception... application is terminating."); } static void DemoThread() { for(int i = 5; i >= 0; i--) { Console.Write("24/{0} =", i); Console.Out.Flush(); Console.WriteLine("{0}", 24 / i); System.Threading.Thread.Sleep(1000); if (exiting) return; } } 

Por lo tanto, en mi opinión, la forma más limpia de manejarlo en una aplicación de consola es garantizar que cada subproceso tenga un controlador de excepción en el nivel raíz:

 static bool exiting = false; static void Main(string[] args) { try { System.Threading.Thread demo = new System.Threading.Thread(DemoThread); demo.Start(); Console.ReadLine(); exiting = true; } catch (Exception ex) { Console.WriteLine("Caught an exception"); } } static void DemoThread() { try { for (int i = 5; i >= 0; i--) { Console.Write("24/{0} =", i); Console.Out.Flush(); Console.WriteLine("{0}", 24 / i); System.Threading.Thread.Sleep(1000); if (exiting) return; } } catch (Exception ex) { Console.WriteLine("Caught an exception on the other thread"); } } 

También necesita manejar excepciones de hilos:

 static void Main(string[] args) { Application.ThreadException += MYThreadHandler; } private void MYThreadHandler(object sender, Threading.ThreadExceptionEventArgs e) { Console.WriteLine(e.Exception.StackTrace); } 

Whoop, lo siento por las formas de ganar, por cualquier hilo que esté usando en una aplicación de consola, deberá encerrarlo en un bloque try / catch. Los subprocesos de fondo que encuentran excepciones no controladas no hacen que la aplicación finalice.

Lo que está intentando debería funcionar de acuerdo con los documentos de MSDN para .Net 2.0. También puede probar una captura / captura en la parte principal alrededor de su punto de entrada para la aplicación de la consola.

 static void Main(string[] args) { try { // Start Working } catch (Exception ex) { // Output/Log Exception } finally { // Clean Up If Needed } } 

Y ahora tu captura manejará cualquier cosa que no haya sido capturada ( en el hilo principal ). Puede ser elegante e incluso reiniciar donde estaba si lo desea, o puede dejar que la aplicación muera y registrar la excepción. Agregarías finalmente si querías hacer una limpieza. Cada hilo requerirá su propio manejo de excepciones de alto nivel similar al principal.

Editado para aclarar el punto sobre los hilos según lo señala BlueMonkMN y se muestra en detalle en su respuesta.