Pregunta

¿Es posible utilizar un controlador de excepciones UnhandledException en un servicio de Windows?

Normalmente, usaría un componente de manejo de excepciones personalizado que realiza registros, llama por teléfono a casa, etc.Este componente agrega un controlador a System.AppDomain.CurrentDomain.UnhandledException pero, hasta donde puedo decir, esto no logra nada en un servicio de Windows, por lo que termino con este patrón en mis 2 (o 4) puntos de entrada del servicio:


    Protected Overrides Sub OnStart(ByVal args() As String)
        ' Add code here to start your service. This method should set things
        ' in motion so your service can do its work.
        Try
            MyServiceComponent.Start()
        Catch ex As Exception
            'call into our exception handler
            MyExceptionHandlingComponent.ManuallyHandleException (ex)
            'zero is the default ExitCode for a successfull exit, so if we set it to non-zero
            ExitCode = -1
            'So, we use Environment.Exit, it seems to be the most appropriate thing to use
            'we pass an exit code here as well, just in case.
            System.Environment.Exit(-1)
        End Try
    End Sub

¿Hay alguna manera de que mi componente de Manejo de excepciones personalizado pueda manejar esto mejor para no tener que llenar mi OnStart con plomería desordenada de manejo de excepciones?

¿Fue útil?

Solución

Ok, he investigado un poco más sobre esto ahora.Cuando crea un servicio de Windows en .Net, crea una clase que hereda de System.ServiceProcess.ServiceBase (en VB esto está oculto en el archivo .Designer.vb).Luego, anula las funciones OnStart y OnStop, y OnPause y OnContinue, si así lo desea.Estos métodos se invocan desde la clase base, así que husmeé un poco con el reflector.OnStart se invoca mediante un método en System.ServiceProcess.ServiceBase llamado ServiceQueuedMainCallback.La versión en mi máquina "System.ServiceProcess, Version=2.0.0.0" se descompila así:


Private Sub ServiceQueuedMainCallback(ByVal state As Object)
    Dim args As String() = DirectCast(state, String())
    Try 
        Me.OnStart(args)
        Me.WriteEventLogEntry(Res.GetString("StartSuccessful"))
        Me.status.checkPoint = 0
        Me.status.waitHint = 0
        Me.status.currentState = 4
    Catch exception As Exception
        Me.WriteEventLogEntry(Res.GetString("StartFailed", New Object() { exception.ToString }), EventLogEntryType.Error)
        Me.status.currentState = 1
    Catch obj1 As Object
        Me.WriteEventLogEntry(Res.GetString("StartFailed", New Object() { String.Empty }), EventLogEntryType.Error)
        Me.status.currentState = 1
    End Try
    Me.startCompletedSignal.Set
End Sub

Entonces, debido a que Me.OnStart(args) se llama desde la parte Try de un bloque Try Catch, asumo que cualquier cosa que suceda dentro del método OnStart está efectivamente envuelta por ese bloque Try Catch y, por lo tanto, cualquier excepción que ocurra no se maneja técnicamente como en realidad, se manejan en ServiceQueuedMainCallback Try Catch.Por lo tanto, CurrentDomain.UnhandledException nunca ocurre al menos durante la rutina de inicio.Los otros 3 puntos de entrada (OnStop, OnPause y OnContinue) se llaman desde la clase base de manera similar.

Así que "creo" que eso explica por qué mi componente de Manejo de excepciones no puede detectar UnhandledException al iniciar y detener, pero no estoy seguro de si explica por qué los temporizadores configurados en OnStart no pueden causar una UnhandledException cuando se activan.

Otros consejos

Puedes suscribirte al Evento AppDomain.UnhandledException.Si tiene un bucle de mensajes, puede vincularlo al Evento Application.ThreadException.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top