Обработчик UnhandledException в .Net службе Windows

Можно ли использовать обработчик UnhandledException в службе Windows?

Обычно я бы использовал пользовательский встроенный компонент обработки исключений, который регистрирует журнал, домашний телефон и т.д. Этот компонент добавляет обработчик к System.AppDomain.CurrentDomain.UnhandledException, но насколько я могу судить об этом, ничего не может добиться от службы Windows поэтому я получаю этот шаблон в моих 2 (или 4) точках входа в службу:


    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

Есть ли способ, которым мой пользовательский компонент обработки исключений может справиться с этим лучше, поэтому мне не нужно заполнять мой OnStart грязной обработкой обработки исключений?

Ответ 1

Хорошо, Ive сделал немного больше исследований в этом сейчас. Когда вы создаете службу Windows в .Net, вы создаете класс, который наследуется от System.ServiceProcess.ServiceBase(в VB это скрыто в файле .Designer.vb). Затем вы переопределяете функции OnStart и OnStop, а также OnPause и OnContinue, если хотите. Эти методы вызываются из базового класса, поэтому я немного задумался о рефлекторе. OnStart вызывается методом в System.ServiceProcess.ServiceBase, называемом ServiceQueuedMainCallback. Vesion на моей машине "System.ServiceProcess, Version = 2.0.0.0" декомпилируется следующим образом:


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

Итак, поскольку Me.OnStart(args) вызывается из части Try в блоке Try Catch, я предполагаю, что все, что происходит внутри метода OnStart, эффективно завершается блоком Try Catch, и поэтому любые возникающие исключения не являются технически необработанных, поскольку они фактически обрабатываются в ServiceQueuedMainCallback Try Catch. Таким образом, CurrentDomain.UnhandledException никогда не происходит, по крайней мере, во время запуска. Остальные 3 точки входа (OnStop, OnPause и OnContinue) вызывается из базового класса аналогичным образом.

Итак, я думаю, что это объясняет, почему мой компонент обработки исключений не может удалить UnhandledException при запуске и остановке, но я не уверен, объясняет ли он, почему таймеры, которые настроены в OnStart, могут вызвать UnhandledException при их запуске.