Восстановление служб Windows без перезапуска службы
Я настраиваю восстановление для служб Windows для перезапуска с одноминутной задержкой после сбоев. Но я никогда не получал его, чтобы фактически перезапустить службу (даже с самыми вопиющими ошибками).
Я получаю сообщение в EventViewer:
Невозможно найти описание для идентификатора события (1) в источнике (MyApp.exe). На локальном компьютере могут не отображаться необходимые данные реестра или файлы DLL сообщений, чтобы отображать сообщения с удаленного компьютера. Вы можете использовать флаг /AUXSOURCE = для получения этого описания; см. "Справка и поддержка". Следующая информация является частью события: Нарушение прав доступа по адресу 00429874 в модуле "MyApp.exe". Запись адреса 00456704.
Есть ли что-то еще, что мне нужно сделать? Есть ли что-то в моем коде (я использую Delphi), который должен быть установлен, чтобы включить это?
Ответы
Ответ 1
Восстановление службы предназначено для обработки случая, когда служба аварийно завершает работу - поэтому, если вы перейдете к taskmgr и щелкните правой кнопкой мыши "конечный процесс" в вашем сервисном процессе, логика восстановления должна зайти. Я не считаю, что восстановление службы логика срабатывает, если ваш сервис выходит изящно (даже если он выходит с ошибкой).
Также сообщение eventvwr указывает, что ваше приложение называется API-интерфейсом ReportEvent, определяющим идентификатор события 1. Но вы не зарегистрировали свои сообщения о событиях с помощью средства просмотра событий, чтобы он не смог преобразовать идентификатор события 1 в значимую текстовую строку.
Ответ 2
Восстановление службы работает только для неожиданного выхода, например (exit (-1)).
Всю дорогу, которую мы используем для остановки службы обычным способом, не будет работать для восстановления.
Если вы хотите остановить службу и хотите восстановить работоспособность, вызовите exit (-1), и вы увидите сообщение об ошибке как "служба остановлена с непредвиденной ошибкой", а затем ваша служба перезапустится как настройка восстановления есть.
Ответ 3
Если вы убиваете службу из диспетчера задач, забыли логику восстановления. В фоновом режиме менеджер задач "убивает" процесс "stop service". и, как можно предположить, это не служебный сбой. Это заставило меня убить его с помощью Visual Studio. В диспетчере задач щелкните правой кнопкой мыши процесс обслуживания. Выберите debug.
В Visual studio выберите Debug- > Terminate All.
И теперь вы имитировали неудачу службы. В этом случае логика восстановления работает нормально.
Ответ 4
Менеджер управления службами попытается перезапустить службу, если вы настроили ее для перезапуска SCM. Это подробно описано здесь в документации для структуры SERVICE_FAILURE_ACTIONS
.
Служба считается неудачной, когда она завершается без сообщения статуса SERVICE_STOPPED сервис-контроллера.
Это можно настроить, установив флаг SERVICE_FAILURE_ACTIONS_FLAG
structure fFailureActionsOnNonCrashFailures
, см. здесь). Вы можете установить этот параметр из апплета "Службы", установив флажок "Включить действия для остановок с ошибками" на вкладке восстановления.
Если этот член имеет значение ИСТИНА и служба настроил действия сбоя, действия сбоя ставятся в очередь, если сервисный процесс завершается без сообщения статуса SERVICE_STOPPED или если он входит в состояние SERVICE_STOPPED, но член dwWin32ExitCode структуры SERVICE_STATUS не является ERROR_SUCCESS (0). Если этот член FALSE, и служба настроила действия сбоя, действия сбоя ставятся в очередь только в том случае, если служба завершает работу без сообщения статуса SERVICE_STOPPED.
Итак, в зависимости от того, как вы структурировали свой сервис, как вы настроили свои действия по сбою и что вы делаете, когда у вас есть "фатальная ошибка", может быть достаточно позвонить ExitProcess()
или exit()
и вернуть не нулевое значение. Тем не менее, вероятно, безопаснее гарантировать, что ваш сервис выйдет без кода, связанного с SCM, сообщающего SCM, что ваша служба достигла состояния SERVICE_STOPPED
. Это гарантирует, что ваши действия по сбою ВСЕГДА произойдут...