2008-09-17 35 views
37

Duplicar posible:
.NET - What’s the best way to implement a “catch all exceptions handler”Cómo capturar todas las excepciones/accidentes en una aplicación .NET

Tengo una aplicación .NET aplicación de consola que está fallando y mostrando un mensaje a la usuario. Todo mi código está en un bloque try{<code>} catch(Exception e){<stuff>}, pero todavía se muestran ocasionalmente errores.

En una aplicación Win32, puede capturar todas las posibles excepciones/accidentes mediante la instalación de varios controladores de excepciones:

/* C++ exc handlers */ 
_set_se_translator 
SetUnhandledExceptionFilter 
_set_purecall_handler 
set_terminate 
set_unexpected 
_set_invalid_parameter_handler 

¿Cuál es el equivalente en el mundo .NET para que pueda manejar/log/quiet todo error posible ¿casos?

+0

Tenga en cuenta que hay [muchas formas de que un proceso se "cuelgue"] (http://stackoverflow.com/questions/3613108/ways-for-an-unmanaged-windows- process-to-crash), cada uno de los cuales puede requerir trucos especiales para capturar: todos estos son adicionales a las formas en que una excepción administrada puede hacer que su aplicación disminuya. Una última complicación es que WinForms, por ejemplo, puede interferir con sus intentos detectando excepciones antes de que lleguen al manejador de excepciones globales de la aplicación. –

Respuesta

26

Al contrario de lo que algunos otros han dicho, no hay nada malo captura todas las excepciones. Lo importante es manejarlos adecuadamente. Si tiene un desbordamiento de pila o una condición de falta de memoria, la aplicación debe cerrarse para ellos. Además, tenga en cuenta que las condiciones OOM pueden evitar que su manejador de excepciones se ejecute correctamente. Por ejemplo, si su manejador de excepciones muestra un cuadro de diálogo con el mensaje de excepción, si no tiene memoria, puede que no haya suficiente para la visualización del diálogo. Lo mejor es iniciar sesión y cerrar de inmediato.

Como han mencionado otros, existen los eventos UnhandledException y ThreadException que puede manejar para excepciones de recopilación que de lo contrario podrían perderse. Luego simplemente arroje un manejador de excepciones alrededor de su ciclo principal (asumiendo una aplicación de winforms).

Además, debe tener en cuenta que las OutOfMemoryExceptions no siempre se lanzan para las condiciones de falta de memoria. Una condición OOM puede desencadenar todo tipo de excepciones, en su código o en el marco, que no necesariamente tienen que ver con el hecho de que la condición real subyacente está fuera de la memoria. Frecuentemente he visto InvalidOperationException o ArgumentException cuando la causa subyacente está realmente fuera de la memoria.

+2

Me sorprende que no haya más votos al respecto. Juanma hizo una buena adición al capturar el evento, sin embargo, eso no cubre todos los escenarios. La información que debe tomarse de esto es que está bien romper estándares a veces. Capture tipos de excepciones específicos con funcionalidad explícita y tenga un contenedor para capturar y manejar cualquier otra cosa. Si está escribiendo un archivo DLL, según mi experiencia, debe tener una clase que herede de la excepción, cree su funcionalidad, ajuste su excepción no controlada dentro de la propiedad InnerException y throw. –

42

Puede agregar un controlador de eventos al evento AppDomain.UnhandledException y se ejecutará cuando se produzca una excepción y no se capture.

+2

La configuración de AppDomain.UnhandledException parece funcionar EXACTAMENTE como llamar a Win32 SetUnhandledExceptionFilter. Si otra parte de su aplicación ha instalado un filtro, AppDomain.UnhandledException se "encadenará" correctamente y también llamará al otro filtro. –

4

Puede usar el dominio de aplicación.CurrentDomain.UnhandledException para obtener un evento.

10

La clase Global.asax es su última línea de defensa. Mira:

protected void Application_Error(Object sender, EventArgs e) 

método

+5

Nota: esta respuesta es para aplicaciones ASP.NET y no para aplicaciones de consola. –

3

También puede ir con Application.ThreadException Evento.

Una vez que estaba desarrollando una aplicación .NET que se ejecuta dentro de una aplicación basada en COM; este evento fue muy útil, ya que AppDomain.CurrentDomain.UnhandledException no funcionó en este caso.

1

Creo que debería preferir no capturar todas las excepciones, pero mejor que se las muestre al usuario. La razón de esto es que solo debes atrapar Excepciones que realmente puedas manejar. Si se encuentra con alguna Excepción que hace que el programa se detenga pero aún lo atrape, esto podría causar problemas mucho más graves. Lea también FAQ: Why does FxCop warn against catch(Exception)?.

+3

Sí, pero sería bueno poder registrar toda la información (seguimiento de la pila, versiones de todas las dependencias, tal vez una captura de pantalla) antes de que la aplicación falle por completo ... – Benjol

6

Tenga en cuenta que una cierta excepción son peligrosos para coger - o casi imposibles de atrapar,

  • OutOfMemoryException: cualquier cosa que haga en el controlador catch podría asignar memoria (en el lado administrados o no administrados de la CLR) y por lo tanto el gatillo OOM
  • StackOverflowException: dependiendo de si el CLR lo detectó con suficiente anticipación, es posible que reciba una notificación. En el peor de los casos, simplemente mata el proceso.
1

Tenga en cuenta que la captura de estas excepciones no controladas puede cambiar los requisitos de seguridad de su aplicación. Su aplicación puede dejar de ejecutarse correctamente en ciertos contextos (cuando se ejecuta desde un recurso compartido de red, etc.). Asegúrate de probarlo a fondo.

4

Aunque capturar todas las excepciones sin el plan para manejarlas correctamente es sin duda una mala práctica, creo que una aplicación debe fallar de alguna manera elegante. Un choque no debería asustar al usuario hasta la muerte, y al menos debería mostrar una descripción del error, cierta información para informar al soporte técnico e, idealmente, un botón para cerrar la aplicación y reiniciarla. En un mundo ideal, la aplicación debería poder volcar en el disco los datos del usuario y luego tratar de recuperarlo (pero veo que esto es pedir demasiado).

De todos modos, yo suelo usar:

AppDomain.CurrentDomain.UnhandledException 
0

no hace daño a utilizar tanto AppDomain.CurrentDomain.UnhandledException Application.ThreadException

pero tenga en cuenta que las excepciones en las discusiones secundarias no son capturados por estos manipuladores; use SafeThread para hilos secundarios si es necesario

+0

Desde MSDN: si el evento UnhandledException se maneja en el dominio de aplicación predeterminado, se genera allí para cualquier excepción no controlada en cualquier subproceso, sin importar en qué dominio de aplicación inició el subproceso. (En algunos casos, no se pueden manejar todos los dominios de aplicación) , pero los hilos en el mismo dominio de aplicación se manejan con certeza ... Por supuesto, esas excepciones capturadas aún pueden terminar la aplicación.) –

+0

@ebyrob: confíe en MSDN, pero verifique;) –

+0

Acabo de verificar que podría detectar las excepciones de Timer y ThreadPool con el evento UnhandledException. (Ambos resultaron en una aplicación muerta) –

Cuestiones relacionadas