Обработчик UnhandledException в .Net Windows Service - PullRequest
25 голосов
/ 12 сентября 2008

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

Ответы [ 2 ]

15 голосов
/ 12 сентября 2008

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

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

2 голосов
/ 12 сентября 2008

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...