2008-10-24 16 views
10

Estoy trabajando en un proyecto para mejorar nuestras capacidades de depuración de producción. Nuestro objetivo es producir de manera confiable un minivolcado en cualquier excepción no controlada, ya sea que la excepción se administre o no, y si se produce en un subproceso administrado o no administrado.¿Cómo funciona SetUnhandledExceptionFilter en aplicaciones .NET WinForms?

Utilizamos la excelente biblioteca ClrDump para esto actualmente, pero no proporciona exactamente las características exactas que necesitamos, y me gustaría entender los mecanismos detrás del filtrado de excepciones, así que me propuse probar esto por mí mismo.

Comencé siguiendo este artículo del blog para instalar un manejador SEH mismo: http://blogs.microsoft.co.il/blogs/sasha/archive/2007/12.aspx. Esta técnica funciona para aplicaciones de consola, pero cuando intento lo mismo desde una aplicación de WinForms, mi filtro no recibe ninguna variedad de excepciones no administradas.

¿Qué puede hacer ClrDump que no estoy haciendo? ClrDump produce volcados en todos los casos, por lo que su filtro de excepción todavía se debe llamar ...

Nota: Conozco las capacidades de ADPlus, y también hemos considerado utilizar las claves de registro de AeDebug ... Estas son también posibilidades , pero también tienen sus compensaciones.

Gracias, de Dave

// Code adapted from <http://blogs.microsoft.co.il/blogs/sasha/archive/2007/12.aspx> 
LONG WINAPI MyExceptionFilter(__in struct _EXCEPTION_POINTERS *ExceptionInfo) 
{ 
    printf("Native exception filter: %X\n",ExceptionInfo->ExceptionRecord->ExceptionCode); 

    Beep(1000,1000); 
    Sleep(500); 
    Beep(1000,1000); 

    if(oldFilter_ == NULL) 
    { 
     return EXCEPTION_CONTINUE_SEARCH; 
    } 

    LONG ret = oldFilter_(ExceptionInfo); 
    printf("Other handler returned %d\n",ret); 

    return ret; 
} 



#pragma managed 

namespace SEHInstaller 
{ 
    public ref class SEHInstall 
    { 
    public: 
     static void InstallHandler() 
     {  
     oldFilter_ = SetUnhandledExceptionFilter(MyExceptionFilter); 
     printf("Installed handler old=%x\n",oldFilter_); 
     } 


    }; 
} 

Respuesta

9

Windows Forms tiene un manejador de excepciones incorporado que hace lo siguiente de forma predeterminada:

  • detecta una excepción conseguido controlada cuando:
    • ningún depurador asociado, y
    • excepción durante la ventana procesamiento de mensajes, y
    • jitDebugging = false en App.Config.
  • Muestra el diálogo al usuario y evita la finalización de la aplicación.

Puede desactivar el primer comportamiento estableciendo jitDebugging = true en app.config. Esto significa que su última oportunidad para detener la finalización de la aplicación es atrapar la excepción no controlada registrándose para el evento Application.ThreadException, p. en C#:

Application.ThreadException += new Threading.ThreadExceptionHandler(CatchFormsExceptions); 

Si decide no detectar la excepción no controlada aquí, entonces usted tendrá que comprobar y/o cambiar la configuración de DbgJitDebugLaunchSetting en HKLM \ Software.NetFramework registro.Esto tiene uno de los tres valores que conozco:

  • 0: muestra el cuadro de diálogo del usuario que pregunta "depurar o terminar".
  • 1: permite la excepción a través de CLR para tratar.
  • 2: inicia el depurador especificado en la clave de registro DbgManagedDebugger.

En Visual Studio, vaya a Herramientas> Opciones> Depuración> JIT para establecer esta clave en 0 o 2. Pero un valor de 1 suele ser el que desea en la máquina de un usuario final. Tenga en cuenta que esta clave de registro se aplica antes del evento de excepción CLR no controlada que usted discute.

A continuación, puede establecer el filtro de excepción nativo que ha discutido.

2

SetUnhandledExceptionFilter instala un controlador que se invoca cuando un Win32-excpetion alcanza la parte superior de una pila de llamadas hilos sin ser manejado.

En muchos idiomas, incluidos los tiempos de ejecución gestionados, las excepciones de idioma se implementan utilizando excepciones de Win32. Sin embargo, el tiempo de ejecución administrado tendrá un bloque __try __catch (...) de nivel superior en la parte superior de cada hilo que atrapará cualquier win32 a las excepciones de tiempo de ejecución y las procesará sin permitirles escapar al controlador de nivel superior de Win32.

El conocimiento del tiempo de ejecución específico sería necesario para inyectar un controlador en este nivel porque las excepciones nunca podrán escapar al controlador TheadProc de Win32.

4

Si desea que sus excepciones hilo GUI que funcionan igual que los de su no-GUI, para que puedan obtener manejan de la misma manera, usted puede hacer esto:

Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException); 

Aquí está el fondo:

en una aplicación GUI manejadas, por defecto, las excepciones que se originan en el hilo de interfaz gráfica de usuario son manejadas por todo lo que está asignado a la Application.ThreadException, que se puede personalizar así:

Application.ThreadException += 
    new System.Threading.ThreadExceptionEventHandler(Application_ThreadException); 

Las excepciones que se originan en los otros hilos son manejados por AppDomain.CurrentDomain.UnhandledException, que se puede personalizar así:

AppDomain.CurrentDomain.UnhandledException += 
    new UnhandledExceptionEventHandler(Program.CurrentDomain_UnhandledException); 

Asignación a UnhandledException funciona exactamente como llamar Win32 SetUnhandledExceptionFilter.

Si su objetivo es crear minivolcados y luego usarlos, necesitará usar las herramientas de depuración para Windows, sos.dll. Tendrá que producir minivolcados MiniDumpWithFullMemory.

Y entonces, incluso entonces, probablemente no tendrá todo lo que pueda desear. System.Diagnostics.StackTrace para obtener la pila de llamadas administradas de llamadas.

Cuestiones relacionadas