Manejo del problema de excepciones no controladas

Quería configurar algún controlador para todas las excepciones inesperadas que podría no haber atrapado dentro de mi código. En Program.Main() utilicé el siguiente código:

 AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(ErrorHandler.HandleException); 

Pero no funcionó como esperaba. Cuando inicié la aplicación en modo de depuración y lancé una excepción, llamó al controlador, pero luego apareció el asistente de excepción en Visual Studio como si la excepción se hubiera producido sin ningún tipo de manipulación. Intenté Application.Exit () dentro del controlador pero no funcionó tan bien.

Lo que me gustaría lograr es que la excepción se maneje con mi controlador y luego la aplicación se cierre bien. ¿Hay alguna otra forma de hacerlo o estoy usando el código anterior de la manera incorrecta?

Es porque lo está ejecutando a través de Visual Studio en modo de depuración. Si libera e instala su aplicación en otro lugar, solo se procesará su manejador global de excepciones.

Normalmente uso algo como esto para tratar de detectar todas las excepciones inesperadas de alto nivel.

 using System; static class Program { [STAThread] static void Main(string[] argv) { try { AppDomain.CurrentDomain.UnhandledException += (sender,e) => FatalExceptionObject(e.ExceptionObject); Application.ThreadException += (sender,e) => FatalExceptionHandler.Handle(e.Exception); // whatever you need/want here Application.Run(new MainWindow()); } catch (Exception huh) { FatalExceptionHandler.Handle(huh); } } static void FatalExceptionObject(object exceptionObject) { var huh = exceptionObject as Exception; if (huh == null) { huh = new NotSupportedException( "Unhandled exception doesn't derive from System.Exception: " + exceptionObject.ToString() ); } FatalExceptionHandler.Handle(huh); } } 

Tal vez es algo que a usted también le resulta útil. Este código principal enruta las tres formas de atrapar excepciones inesperadas de alto nivel a través de una llamada a un método. Todo lo que necesita ahora es una clase estática FatalExceptionHandler que incluye su manejo de excepción de nivel superior en su método Handle .

Y realmente, cualquier desarrollador de aplicaciones sabe que en realidad solo hay dos cosas que hacer allí:

  1. Muestra / registra la excepción como mejor te parezca
  2. Asegúrese de salir / matar el proceso de solicitud

Si piensas que el elemento dos es extraño, recuerda que solo nos molestamos en hacer esto en primer lugar para situaciones realmente excepcionales. Estas cosas probablemente son errores que necesitan cambios en su aplicación para ser tratados con precisión. Cualquier otro manejo de excepciones, el tipo funcional, debe estar más abajo dentro de su código de progtwig real, captando tipos específicos de excepciones donde esto tenga sentido y manipularlas allí de la manera que tenga sentido. Cualquier otra cosa debería aparecer en tu FatalExceptionHandler para darse a conocer y evitar que el progtwig posiblemente lisiado funcione desde un estado dañado.

Los progtwigs muertos no dicen mentiras … 😉

Tenga en cuenta que las excepciones no controladas siguen siendo bastante fatales; solo puedes utilizar esto para iniciar sesión, o tal vez un cierre apresurado. Ni esto ni Application.ThreadException se pueden usar como sumidero global de errores.

El mejor enfoque es agregar un manejo adecuado, por ejemplo, alrededor de toda su lógica Main() . Tenga en cuenta que incluso esto no puede detectar algunas excepciones, como los errores durante la carga de formulario (que se vuelven especialmente desagradables, puede atraparlos con un depurador adjunto, pero no sin).

Quizás lo que estás buscando es Environment.Exit(int errorcode)

Ese comportamiento es por diseño.

Pero hay una solución alternativa.

O llama a Process.GetCurrentProcess().Kill(); dentro del controlador, o simplemente no dejes que el controlador finalice.

Mira el ejemplo:

 class Program { void Run() { AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException); Console.WriteLine("Press enter to exit."); do { (new Thread(delegate() { throw new ArgumentException("ha-ha"); })).Start(); } while (Console.ReadLine().Trim().ToLowerInvariant() == "x"); Console.WriteLine("last good-bye"); } int r = 0; void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) { Interlocked.Increment(ref r); Console.WriteLine("handled. {0}", r); Console.WriteLine("Terminating " + e.IsTerminating.ToString()); Thread.CurrentThread.IsBackground = true; Thread.CurrentThread.Name = "Dead thread"; while (true) Thread.Sleep(TimeSpan.FromHours(1)); //Process.GetCurrentProcess().Kill(); } static void Main(string[] args) { Console.WriteLine("..."); (new Program()).Run(); } } 

Esto no debería ser un receptor predeterminado para excepciones, seguramente.

Pero esto debe hacerse para informar excepciones con gracia.