Можно ли использовать обработчик 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
Есть ли способ, которым мой компонент Custom Exception Handling может справиться с этим лучше, чтобы мне не приходилось заполнять свой OnStart беспорядочной сантехникой для обработки исключений?





Вы можете подписаться на AppDomain.UnhandledException событие. Если у вас есть цикл сообщений, вы можете привязать к Application.ThreadException событие.
Хорошо, сейчас я немного исследовал это. Когда вы создаете службу 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 никогда не возникает, по крайней мере, во время процедуры запуска. Остальные 3 точки входа (OnStop, OnPause и OnContinue) вызываются из базового класса аналогичным образом.
Итак, я «думаю», что это объясняет, почему мой компонент обработки исключений не может поймать UnhandledException при запуске и остановке, но я не уверен, объясняет ли это, почему таймеры, установленные в OnStart, не могут вызывать UnhandledException при срабатывании.
Я обнаружил, что событие UnhandledException в службе действительно получает исключения в других потоках, если вы очень рано подключаете обработчик событий. Я подключил его к конструктору службы, а не к методу OnStart (). Это также удаляет уродливые исключения из вашего OnStart ().
учитывая, что мой ответ вам был удален (несколько лет назад), я подумал, что верну его как комментарий, что и должно было быть всегда: Спасибо за ответ, Гаро, но, как я сказал в своем исходном вопросе, наше исключение обработчик добавляет обработчик к System.AppDomain.CurrentDomain.UnhandledException, он просто не работает при использовании в контексте службы Windows.