Функция Service ServiceMain

Когда программа управления службами запрашивает запуск новой службы, диспетчер управления службами (SCM) запускает службу и отправляет запрос на запуск диспетчеру управления. Диспетчер управления создает новый поток для выполнения функции ServiceMain для службы. Пример см. в разделе Написание функции ServiceMain.

Функция ServiceMain должна выполнять следующие задачи:

  1. Инициализация всех глобальных переменных.

  2. Немедленно вызовите функцию RegisterServiceCtrlHandler , чтобы зарегистрировать функцию Handler для обработки запросов управления для службы. Возвращаемое значение RegisterServiceCtrlHandler — это дескриптор состояния службы , который будет использоваться в вызовах для уведомления SCM о состоянии службы.

  3. Выполните инициализацию. Если ожидается, что время выполнения кода инициализации будет очень коротким (менее одной секунды), инициализацию можно выполнить непосредственно в 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 и использовать значение для передачи пользователю сведений о ходе выполнения.

  4. После завершения инициализации вызовите SetServiceStatus , чтобы задать состояние службы SERVICE_RUNNING и указать элементы управления, которые служба готова принять. Список элементов управления см. в разделе структура SERVICE_STATUS .

  5. Выполните задачи службы или, если нет ожидающих задач, верните управление вызывающей объекту. Любое изменение состояния службы требует вызова SetServiceStatus для передачи новых сведений о состоянии.

  6. Если во время инициализации или запуска службы возникает ошибка, служба должна вызвать SetServiceStatus , чтобы задать состояние службы SERVICE_STOP_PENDING, если очистка будет длительной. После завершения очистки вызовите SetServiceStatus , чтобы задать состояние службы SERVICE_STOPPED из последнего потока для завершения. Не забудьте задать элементы dwServiceSpecificExitCode и dwWin32ExitCode структуры SERVICE_STATUS , чтобы определить ошибку.

Написание функции ServiceMain