Question

Est-il possible d'utiliser un gestionnaire UnhandledException dans un service Windows ?

Normalement, j'utiliserais un composant de gestion des exceptions personnalisé qui effectue la journalisation, le téléphone à la maison, etc.Ce composant ajoute un gestionnaire à System.AppDomain.CurrentDomain.UnhandledException mais pour autant que je sache, cela ne permet pas de gagner un service Windows, je me retrouve donc avec ce modèle dans mes 2 (ou 4) points d'entrée de service :


    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

Existe-t-il un moyen pour mon composant de gestion des exceptions personnalisées de mieux gérer cela afin que je n'aie pas à remplir mon OnStart avec une plomberie de gestion des exceptions désordonnée ?

Était-ce utile?

La solution

Ok, j'ai fait un peu plus de recherches à ce sujet maintenant.Lorsque vous créez un service Windows dans .Net, vous créez une classe qui hérite de System.ServiceProcess.ServiceBase (en VB, elle est cachée dans le fichier .Designer.vb).Vous remplacez ensuite les fonctions OnStart et OnStop, ainsi que OnPause et OnContinue si vous le souhaitez.Ces méthodes sont invoquées depuis la classe de base, j'ai donc fouillé un peu avec le réflecteur.OnStart est invoqué par une méthode dans System.ServiceProcess.ServiceBase appelée ServiceQueuedMainCallback.La version sur ma machine "System.ServiceProcess, Version=2.0.0.0" se décompile comme ceci :


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

Donc, parce que Me.OnStart(args) est appelé depuis la partie Try d'un bloc Try Catch, je suppose que tout ce qui se passe dans la méthode OnStart est effectivement encapsulé par ce bloc Try Catch et donc toutes les exceptions qui se produisent ne sont pas techniquement gérées comme ils sont en fait gérés dans ServiceQueuedMainCallback Try Catch.Ainsi, CurrentDomain.UnhandledException ne se produit jamais, au moins pendant la routine de démarrage.Les 3 autres points d'entrée (OnStop, OnPause et OnContinue) sont tous appelés depuis la classe de base de la même manière.

Donc, je « pense » que cela explique pourquoi mon composant de gestion des exceptions ne peut pas intercepter UnhandledException au démarrage et à l'arrêt, mais je ne sais pas si cela explique pourquoi les minuteries configurées dans OnStart ne peuvent pas provoquer une UnhandledException lorsqu'elles se déclenchent.

Autres conseils

Vous pouvez vous abonner au Événement AppDomain.UnhandledException.Si vous disposez d'une boucle de messages, vous pouvez la lier au Événement Application.ThreadException.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top