Функция обработчика управления службой
Каждая служба имеет обработчик управления, функцию Handler , которая вызывается диспетчером управления, когда процесс службы получает запрос на управление из программы управления службой. Таким образом, эта функция выполняется в контексте диспетчера управления. Пример см. в разделе Написание функции обработчика элементов управления.
Служба вызывает функцию RegisterServiceCtrlHandler или RegisterServiceCtrlHandlerEx для регистрации функции обработчика управления службой.
При вызове обработчика управления службой служба должна вызвать функцию SetServiceStatus , чтобы сообщить о своем состоянии SCM только в том случае, если обработка кода элемента управления приводит к изменению состояния службы. Если обработка кода элемента управления не приводит к изменению состояния службы, нет необходимости вызывать SetServiceStatus.
Программа управления службой может отправлять запросы управления с помощью функции ControlService . Все службы должны принимать и обрабатывать код управления SERVICE_CONTROL_INTERROGATE . Вы можете включить или отключить принятие других кодов управления, вызвав SetServiceStatus. Чтобы получить управляющий код SERVICE_CONTROL_DEVICEEVENT , необходимо вызвать функцию RegisterDeviceNotification . Службы также могут обрабатывать дополнительные пользовательские коды управления.
Если служба принимает код управления SERVICE_CONTROL_STOP , она должна остановиться после получения, перейдя в состояние SERVICE_STOP_PENDING или SERVICE_STOPPED . После того как SCM отправит этот управляющий код, он не будет отправлять другие коды управления.
Windows XP: Если служба возвращает NO_ERROR и продолжает работать, она продолжает получать коды управления. Это поведение изменилось начиная с Windows Server 2003 и Windows XP с пакетом обновления 2 (SP2).
Обработчик элемента управления должен вернуться в течение 30 секунд, иначе SCM возвращает ошибку. Если служба должна выполнять длительную обработку, когда служба выполняет обработчик элемента управления, она должна создать дополнительный поток для выполнения длительной обработки, а затем вернуться из обработчика элемента управления. Это не позволяет службе привязывать диспетчер управления. Например, при обработке запроса на остановку для службы, которая занимает много времени, создайте другой поток для обработки процесса остановки. Обработчик элемента управления должен просто вызвать SetServiceStatus с сообщением SERVICE_STOP_PENDING и вернуться.
Когда пользователь завершает работу системы, все обработчики управления, которые вызвали SetServiceStatus с кодом элемента управления SERVICE_ACCEPT_PRESHUTDOWN , получают код элемента управления SERVICE_CONTROL_PRESHUTDOWN . Диспетчер управления службами ожидает, пока служба остановится или не истечет указанное значение времени ожидания перед завершением (это значение можно задать с помощью функции ChangeServiceConfig2 ). Этот управляющий код следует использовать только в особых обстоятельствах, так как служба, обрабатывающая это уведомление, блокирует завершение работы системы до тех пор, пока служба не остановится или не истечет интервал времени ожидания перед завершением.
После завершения предварительных уведомлений все обработчики элементов управления, которые вызвали SetServiceStatus с кодом элемента управления SERVICE_ACCEPT_SHUTDOWN , получают код элемента управления SERVICE_CONTROL_SHUTDOWN . Они получают уведомления в том порядке, в котором они отображаются в базе данных установленных служб. По умолчанию у службы есть около 20 секунд на выполнение задач очистки, прежде чем система завершит работу. По истечении этого времени завершение работы системы продолжается независимо от того, завершено ли завершение работы службы. Обратите внимание, что если система остается в состоянии завершения работы (не перезапущена или отключена), служба продолжает работать.
Если службе требуется больше времени для очистки, она отправляет STOP_PENDING сообщения о состоянии вместе с подсказкой ожидания, поэтому контроллер службы знает, сколько времени следует ждать, прежде чем сообщить системе о завершении работы службы. Тем не менее, чтобы предотвратить остановку работы службы, существует ограничение на время ожидания контроллера службы. Если служба завершается с помощью оснастки "Службы", это ограничение составляет 125 секунд или 125 000 миллисекунд. Если операционная система перезагружается, ограничение времени указывается в значении WaitToKillServiceTimeout (в миллисекундах) следующего раздела реестра:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control
Важно!
Служба не должна пытаться увеличить ограничение времени, изменив это значение. Если необходимо вручную задать WaitToKillServiceTimeout , значение должно быть в миллисекундах.
Клиентам требуется быстрое завершение работы операционной системы. Например, если компьютер, работающий под управлением импетного питания, не может завершить работу до того, как импет не будет работать, данные могут быть потеряны. Таким образом, службы должны выполнять свои задачи очистки как можно быстрее. Рекомендуется свести к минимуму несохраненные данные, регулярно сохраняя данные, отслеживая данные, сохраненные на диске, и сохраняя несохраненные данные только при завершении работы. Так как компьютер завершает работу, не тратьте время на освобождение выделенной памяти или других системных ресурсов. Если необходимо уведомить сервер о выходе, сведите к минимуму время, затрачиваемое на ожидание ответа, так как проблемы с сетью могут задержать завершение работы службы.
Обратите внимание, что во время завершения работы службы по умолчанию SCM не учитывает зависимости. SCM перечисляет список запущенных служб и отправляет команду SERVICE_CONTROL_SHUTDOWN . Таким образом, служба может завершиться сбоем, так как другая служба, от которого она зависит, уже остановлена.
Чтобы задать порядок завершения работы служб вручную, создайте значение реестра с несколькими строками, содержащее имена служб в том порядке, в котором они должны быть завершены, и назначьте его значению PreshutdownOrder раздела Control следующим образом:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\PreshutdownOrder="Shutdown Order"
Чтобы задать порядок завершения работы зависимых служб из приложения, используйте функцию SetProcessShutdownParameters . SCM использует эту функцию для предоставления обработчику приоритета 0x1E0. SCM отправляет SERVICE_CONTROL_SHUTDOWN уведомления при вызове обработчика управления и ожидает выхода служб, прежде чем вернуться из обработчика управления.
Связанные темы