Вопрос

Можно ли использовать обработчик 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 беспорядочной обработкой исключений?

Это было полезно?

Решение

Хорошо, теперь я провел еще немного исследования по этому поводу.Когда вы создаете службу Windows в .Net, вы создаете класс, который наследуется от System.ServiceProcess.ServiceBase (в VB он скрыт в файле .Designer.vb).Затем вы переопределяете функции OnStart и OnStop, а также OnPause и OnContinue, если захотите.Эти методы вызываются из базового класса, поэтому я немного поковырялся с отражателем.OnStart вызывается методом в System.ServiceProcess.ServiceBase, который называется ServiceQueuedMainCallback.Версия на моей машине «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 на самом деле никогда не происходит, по крайней мере, во время процедуры запуска.Остальные три точки входа (OnStop, OnPause и OnContinue) вызываются из базового класса аналогичным образом.

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

Другие советы

Вы можете подписаться на Событие AppDomain.UnhandledException.Если у вас есть цикл сообщений, вы можете привязать его к Событие Application.ThreadException.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top