Функция ServiceMain
Когда программа управления службами запрашивает запуск новой службы, диспетчер управления службами (SCM) запускает службу и отправляет начальный запрос диспетчеру управления. Диспетчер элементов управления создает новый поток для выполнения функции ServiceMain для службы. Пример см. в записи функции ServiceMain.
Функция ServiceMain должна выполнять следующие задачи:
Инициализировать все глобальные переменные.
Вызовите функцию RegisterServiceCtrlHandler немедленно, чтобы зарегистрировать функциюобработчикадля обработки запросов управления для службы. Возвращаемое значение RegisterServiceCtrlHandler — это дескрип тор состояния службы, который будет использоваться в вызовах для уведомления SCM о состоянии службы.
Выполните инициализацию. Если время выполнения кода инициализации, как ожидается, будет очень коротким (менее одной секунды), инициализация может выполняться непосредственно в ServiceMain.
Если время инициализации, как ожидается, больше одной секунды, служба должна использовать один из следующих методов инициализации:
Вызовите функцию setServiceStatus, чтобы сообщить SERVICE_RUNNING, но не принимать элементы управления до завершения инициализации. Эта служба выполняет это путем вызова SetServiceStatus с dwCurrentState для SERVICE_RUNNING и dwControlsAccepted значение 0 в структуре SERVICE_STATUS. Это гарантирует, что SCM не будет отправлять запросы на управление службой до его готовности и освобождает SCM для управления другими службами. Этот подход к инициализации рекомендуется для производительности, особенно для служб автозапуска.
Отчет SERVICE_START_PENDING, не принимать элементы управления и указывать подсказку ожидания. Если код инициализации службы выполняет задачи, которые, как ожидается, занимает больше времени, чем начальное значение подсказки ожидания, код должен периодически вызывать функцию SetServiceStatus (возможно, с измененным указанием ожидания), чтобы указать, что прогресс выполняется. Не забудьте вызвать SetServiceStatus только в том случае, если инициализация выполняется. В противном случае служба SCM может дождаться ввода состояния SERVICE_RUNNING при условии, что служба выполняет ход выполнения и блокирует запуск других служб. Не вызывайте SetServiceStatus из отдельного потока, если вы не уверены, что поток, выполняющий инициализацию, действительно выполняет прогресс.
Служба, использующая этот подход, также может указывать значение контрольной точки и периодически увеличивать значение во время длительной инициализации. Программа, запущенная службой, может вызывать QueryServiceStatus или QueryServiceStatusEx, чтобы получить последнее значение контрольной точки из SCM и использовать значение для получения добавочного хода выполнения пользователю.
По завершении инициализации вызовите SetServiceStatus, чтобы задать состояние службы SERVICE_RUNNING и указать элементы управления, которые служба готова принять. Список элементов управления см. в SERVICE_STATUS структуре.
Выполните задачи службы или, если нет ожидающих задач, верните управление вызывающей стороны. Любое изменение состояния службы гарантирует вызов SetServiceStatus сообщить о новых сведениях о состоянии.
Если при инициализации или запуске службы возникает ошибка, служба должна вызывать SetServiceStatus, чтобы задать состояние службы SERVICE_STOP_PENDING если очистка будет длинна. После завершения очистки вызовите SetServiceStatus, чтобы задать состояние службы SERVICE_STOPPED из последнего потока, чтобы завершить работу. Не забудьте задать dwServiceSpecificExitCode и dwWin32ExitCode членов структуры SERVICE_STATUS, чтобы определить ошибку.
Связанные разделы