Вспомогательное средство для разработки служб windows nt

Рис. 1. Архитектура системных служб Windows NT

Содержание

  1. Управление системными службами Windows NT
  2. Часть 1
  3. Введение
  4. О демонстрационных программах
  5. Соединение с менеджером системных служб
  6. Функция OpenSCManager
  7. Соединение c другим компьютером
  8. Чтение и изменение конфигурации служб
  9. Параметры конфигурации системной службы
  10. Название и внутреннее имя службы
  11. Описание службы
  12. Тип службы
  13. Исполняемый файл
  14. Способ запуска
  15. Реакция на ошибки при загрузке системы
  16. Группа загрузки
  17. Зависимости
  18. Учетная запись службы
  19. Действия при сбое
  20. Дескриптор безопасности
  21. Функции чтения и изменения конфигурации
  22. QueryServiceConfig
  23. ChangeServiceConfig
  24. QueryServiceConfig2
  25. ChangeServiceConfig2
  26. Пример: получение конфигурационной информации службы
  27. Продолжение следует

Управление системными службами Windows NT

Часть 1

Автор: Александр Федотов

Опубликовано: 24.03.2002
Исправлено: 11.01.2010

Введение

svcarch
Рис. 1. Архитектура системных служб Windows NT

В этой статье мы постараемся не затрагивать вопросы программирования системных служб (хотя полностью их избежать не удастся). Вместо этого, мы сконцентрируемся на вопросах создания управляющих программ, которые почему-то обходятся стороной многими авторами. Мы будем рассматривать только службы Win32, хотя многие конфигурационные параметры и системные функции одинаково применимы и к службам ядра. Прочитав эту статью, вы досконально изучите окружение, в котором выполняются системные службы. Это поможет вам как при создании своих служб, так и при взаимодействии с другими службами.

О демонстрационных программах

svcadmin
Рис. 2. Программа «Администратор системных служб»

voidsvc можно зарегистрировать несколько раз с разными именами. Для установки службы используется командная строка следующего вида:

Удаление службы выполняется аналогично:

Соединение с менеджером системных служб

Функция OpenSCManager

При успешном завершении эта функция возвращает handle менеджера системных служб. Этот handle используется в дальнейшем в качестве параметра для других функций. Ниже приведено подробное описание параметров этой функции.

Этот параметр задает имя компьютера, с менеджером системных служб которого нужно соединиться. Для соединения с SCM на локальном компьютере достаточно указать значение NULL или пустую строку. Если же требуется соединиться с другим компьютером, то перед его именем должно быть указано два обратных слэша, например, «\MYCOMPUTER».

Однако попытка вызвать OpenSCManager с таким параметром приводит к ошибке с кодом ERROR_DATABASE_DOES_NOT_EXIST на всех доступных мне версиях операционной системы, начиная Windows NT 4.0 и заканчивая Windows XP.

Этот параметр задает виды доступа, которые вызывающая программа предполагает использовать при работе с SCM. Как и для многих других объектов, подсистема безопасности Windows NT проверяет указанные флаги доступа на соответствие дескриптору безопасности, ассоциированному с менеджером системных служб, и разрешает или запрещает доступ к менеджеру.

Права доступа, определенные для менеджера системных служб, приведены в таблице 1. Стандартные права доступа не имеют большого смысла для менеджера системных служб, потому что Win32 API не предоставляет функций, которые могли бы реализовать эти права. Другими словами, ни удалить менеджер системных служб, ни манипулировать его дескриптором безопасности нельзя.

Право доступа Описание
SC_MANAGER_CONNECT Подключение к менеджеру системных служб
SC_MANAGER_ENUMERATE_SERVICE Перечисление системных служб с помошью EnumServicesStatus
SC_MANAGER_QUERY_LOCK_STATUS Определение состояния блокировки с помощью QueryServiceLockStatus
SC_MANAGER_CREATE_SERVICE Создание новой системной службы с помошью CreateService
SC_MANAGER_LOCK Захват блокировки базы данных системных служб посредством LockServiceDatabase
SC_MANAGER_MODIFY_BOOT_CONFIG Сохранение статуса загрузки с помощью функции NotifyBootConfigStatus
SC_MANAGER_ALL_ACCESS Эта константа объединяет все перечисленные выше флаги доступа, а также четыре стандартных права доступа: READ_CONTROL, WRITE_DAC, WRITE_OWNER и DELETE.

Таблица 1. Права доступа к менеджеру системных служб

Содержимое дескриптора безопасности SCM документировано в статье Q179249 базы знаний MSDN:

Everyone (Все) * SC_MANAGER_CONNECT
SC_MANAGER_ENUMERATE_SERVICE
SC_MANAGER_QUERY_LOCK_STATUS
System (Система) SC_MANAGER_CONNECT
SC_MANAGER_ENUMERATE_SERVICE
SC_MANAGER_QUERY_LOCK_STATUS
SC_MANAGER_MODIFY_BOOT_CONFIG
Administrators (Администраторы) SC_MANAGER_ALL_ACCESS

* В Windows XP вместо группы Everyone используется группа Authenticated Users (Прошедшие проверку)

На практике это означает, что только администраторы могут устанавливать новые службы в системе, в то время как все пользователи могут получить список установленных служб.

Соединение c другим компьютером

Параметры OpenSCManager весьма очевидны, и, на первый взгляд, не должно быть никаких проблем соединиться с другим компьютером. Все что нужно сделать, это передать функции правильно сформированное имя компьютера (как вы помните, функция требует два обратных слэша в начале имени).

Таким образом, нам нужен способ явным образом задать имя пользователя и пароль, с которыми будет производиться подключение к удаленному компьютеру, но OpenSCManager не предоставляет такой возможности. Решение проблемы нам может подсказать то, что соединение с менеджером системных служб на удаленном компьютере реализовано с использованием протокола SMB. Это тот же самый протокол, который еще со времен Lan Manager используется для доступа к дискам и принтерам других компьютеров, только в нашем случае подключение производится к ресурсу со специальным именем IPC$.

Листинг 1 содержит пример функции, которая устанавливает соединение со SCM на удаленном компьютере, используя указанные имя пользователя и пароль для входа на удаленную систему.

Остается только заметить, что некоторые другие сервисы Windows, такие, как удаленный доступ к реестру посредством RegConnectRegistry и удаленный доступ к счетчикам производительности, реализованы сходным образом, поэтому описанный метод аутентификации применим и к ним в полном объеме.

Теперь, когда мы знаем, как соединиться с менеджером системных служб, давайте вернемся к нашей основной теме и посмотрим, что же можно сделать после того, как соединение установлено.

Чтение и изменение конфигурации служб

Мы начнем наше погружение в глубины управления системными службами с рассмотрения конфигурационных параметров служб, потому что все остальные задачи так или иначе связаны с параметрами конфигурации. Например, если мы хотим установить новую службу, необходимо указать конфигурацию для создаваемой службы. Если мы запускаем или останавливаем службу, параметры конфигурации также оказывают влияние на этот процесс.

Параметры конфигурации системной службы

Конфигурация каждой системной службы описывается фиксированным набором параметров, которые перечислены ниже:

Менеджер системных служб хранит информацию о конфигурации служб в ключе реестра

Каждой системной службе соответствует подключ, имя которого совпадает с именем службы. Подключи служб, в свою очередь, содержат набор именованных значений, которые и задают параметры службы. Список всех значений приведен в таблице 2.

Имя Тип Назначение
DisplayName REG_SZ Название службы
Description REG_SZ Описание службы
ImagePath REG_EXPAND_SZ Путь к исполняемому файлу службы
Type REG_DWORD Тип службы
Start REG_DWORD Способ запуска службы
ErrorControl REG_DWORD Реакция на ошибки при загрузке системы
DependOnService REG_MULTI_SZ Службы, от которых зависит данная служба
DependOnGroup REG_MULTI_SZ Группы загрузки, от которых зависит данная служба
Group REG_SZ Группа загрузки, которой принадлежит служба
ObjectName REG_SZ Учетная запись службы
FailureActions REG_BINARY Действия при сбое

Таблица 2. Параметры конфигурации службы в реестре

Дескриптор безопасности хранится в отдельном подключе с именем Security.

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

Название и внутреннее имя службы

На внутреннее имя службы накладываются определенные ограничения: оно не должно содержать символов ‘/’ и ‘’ и его длина не должна превышать 256 символов. Название ограничено только по длине, которая также не должна быть более 256 символов.

И название, и внутреннее имя службы должны быть уникальными. Вы не сможете создать новую службу, если одно из этих имен уже используется другой службой. Хотя менеджер системных служб сохраняет регистр букв в именах служб, все сравнения производятся без учета регистра. Это означает, что, например, имена «MyService» и «myservice» считаются эквивалентными.

Менеджер системных служб предоставляет две функции, позволяющие по внутреннему имени службы получить ее название, и наоборот:

Описание службы

Начиная с Windows 2000, с каждой системной службой можно ассоциировать краткое описание, которое поясняет назначение службы для пользователей. Например, вот так выглядит описание для службы RunAs:

Позволяет запускать процессы от имени другого пользователя.

Тип службы

Этот атрибут задает тип системной службы. Он может принимать одно из четырех значений:

Кроме того, для служб Win32, выполняющихся в контексте системной учетной записи, может быть установлен следующий флаг:

Таким образом, существует два вида служб Win32: выполняющиеся в отдельном процессе и разделяющие процесс с другими службами. Зачем сделано такое различие, почему бы не запускать каждую службу в отдельном процессе? Ответ: для экономии ресурсов. В системе существует довольно много относительно небольших служб, и с каждой версией системы их количество растет. Выполнять каждую из них в отдельном процессе было бы слишком расточительно.

Однако совместное использование процесса несколькими службами имеет и свои недостатки. Прежде всего, это снижающаяся надежность, ведь сбой в одной из служб может привести к отказу всех остальных служб, выполняющихся в этом процессе. Кроме того, это накладывает определенные ограничения со стороны безопасности. В NT 4 и более ранних версиях Windows NT, только службы, выполняющиеся в контексте системной учетной записи (LocalSystem), могли совместно использовать один процесс. В последующих версиях системы это ограничение снято, но все службы в процессе должны быть зарегистрированы под одной учетной записью.

svchost
Рис. 3. Многие службы Windows 2000 и Windows XP выполняются в процессе svchost.exe

В Windows NT каждый выполняющийся процесс имеет ассоциированную оконную станцию и рабочий стол (window station и desktop). Эти объекты предназначены для разграничения доступа к объектам подсистем User и GDI, таким как окна и перехватчики сообщений (hooks).

Объект оконной станции содержит в себе буфер обмена (clipboard), набор глобальных атомов и набор объектов рабочих столов. Одна из оконных станций, а именно оконная станция с именем WinSta0, является интерактивной. Эта станция видна интерактивному пользователю, она может получать события ввода, такие, как нажатия клавиш на клавиатуре. Все остальные оконные станции являются неинтерактивными, они никогда не видны интерактивному пользователю и не могут получать события ввода.

То, с какой рабочей станцией связан процесс, влияет на его возможность взаимодействия с другими процессами. Например, оконные сообщения можно посылать только в пределах одного рабочего стола. Если попытаться послать сообщение окну с другого рабочего стола, то сообщение не дойдет, так, как будто этого окна не существует. Перехватчики сообщений получают только сообщения на текущем рабочем столе, они не получают сообщений, адресованных окнам на других рабочих столах.

Я думаю, уже достаточно сказано, чтобы вы задали себе вопрос и с нетерпением ожидали от меня ответа: так на какой же оконной станции и рабочем столе выполняются системные службы? Что ж, ответ зависит от учетной записи, под которой зарегистрирована служба, и от наличия флага SERVICE_INTERACTIVE_PROCESS:

Service-0x0-3e7$default Учетной записью службы является LocalSystem и флаг SERVICE_INTERACTIVE_PROCESS не установлен
Winsta0default Учетной записью службы является LocalSystem и флаг SERVICE_INTERACTIVE_PROCESS установлен
Service-0xX-Y$default Учетная запись службы отлична от LocalSystem; X и Y здесь обозначают части идентификатора логон-сессии

Таким образом, если установлен флаг SERVICE_INTERACTIVE_PROCESS (что, напомню, можно сделать только для службы, выполняющейся в контексте системной учетной записи), то служба будет выполняться на той же оконной станции и том же рабочем столе, что и приложения интерактивного пользователя. Это позволит службе создавать окна, которые будут видимы пользователю, устанавливать перехватчики сообщений, которые будут получать сообщения из пользовательских приложений и т.д. Такая служба называется интерактивной.

Если же этот флаг не установлен, то служба будет неинтерактивной и не будет иметь доступа к рабочему столу пользователя (впрочем, при наличии достаточных привилегий изначально неинтерактивная служба может получить доступ к рабочему столу пользователя, но это тема для отдельной статьи [5]). Создаваемые службой окна будут невидимы, и она не сможет получать события ввода. Поскольку системные службы изначально предназначены для выполнения фоновых задач, не требующих вмешательства пользователя, большинство служб являются неинтерактивными.

Исполняемый файл

Например, если путь к службе указан как

При задании командной строки для служб, которые должны совместно использовать один процесс, следует иметь в виду, что службы будут исполняться в одном процессе, только если их командные строки совпадают без учета регистра символов. Например, если командные строки заданы следующим образом,

службы будут запущены в одном процессе, а если добавить хотя бы один лишний пробел,

то для каждой службы будет создан свой собственный процесс.

Способ запуска

Способ запуска определяет, каким образом запускается системная служба. Для служб Win32 этот параметр может принимать одно из трех значений:

Последнее значение может быть полезным для борьбы с программами, запускающими службы, запуск которых нежелателен.

Для служб, запускающихся автоматически, порядок запуска определяется принадлежностью службы к группе загрузки (load order group) и зависимостями от других служб. Мы рассмотрим порядок запуска более подробно, когда будем говорить о группе загрузки и зависимостях службы.

Реакция на ошибки при загрузке системы

Этот параметр конфигурации задает реакцию менеджера системных служб в случае, если служба, отмеченная для автоматического запуска при старте системы, не может быть запущена. Параметр может принимать одно из четырех значений:

Флаги SERVICE_ERROR_SEVERE и SERVICE_ERROR_CRITICAL используются главным образом драйверами устройств. В стандартной установке Windows NT ни одна из служб Win32 не имеет такого типа реакции на ошибки при загрузке системы.

Менеджер системных служб хранит копию конфигурационной базы данных для последней успешной загрузки системы. Если служба или драйвер, отмеченные флагом SERVICE_ERROR_SEVERE или SERVICE_ERROR_CRITICAL, по каким-либо причинам не загружаются, система пытается загрузиться заново, используя сохраненную базу данных. Это дает шанс системному администратору загрузить систему и исправить ошибку в конфигурации.

Такое определение успешной загрузки хорошо подходит для интерактивной рабочей станции, но не очень годится для сервера, который работает без участия человека. Например, система, специально выделенная для работы Web-сервера, вряд ли может считаться загруженной успешно, если служба Web-cервера не запустилась. В то же время, наличие успешного интерактивного входа в систему в этом случае не так важно.

Операционная система предоставляет возможность изменения логики успешной загрузки. Прежде всего, можно запретить Winlogon сообщать об успешной загрузке, для чего в ключе реестра

следует установить значение ReportBootOK в ноль. Теперь ответственность за вызов NotifyBootConfigStatus и, тем самым, признание загрузки успешной лежит на вас. Это можно сделать двумя способами.

Если же требуется более сложная логика, то существует возможность написать свою собственную программу проверки и зарегистрировать ее в ключе реестра

Группа загрузки

Многие службы полагаются в своей работе на другие службы. Например, любая служба, являющаяся также и COM-сервером, может работать, только если запущена служба удаленного вызова процедур (RPC). При автоматическом запуске служб в процессе загрузки системы необходимо обеспечить такую последовательность запуска, чтобы при запуске каждой службы все необходимые ей службы уже работали. Менеджер системных служб решает эту задачу двумя способами: объединением служб в группы загрузки и заданием зависимостей между службами.

Менеджер системных служб хранит список групп загрузки в ключе реестра

Значение List в этом ключе, имеющее тип REG_MULTI_SZ, перечисляет группы загрузки в том порядке, в котором они должны загружаться. Сразу после установки системы список содержит около 30 стандартных групп, которые используются главным образом драйверами устройств. Запустив Администратор системных служб (демонстрационное приложение для этой статьи), вы найдете, что относительно немного служб Win32 принадлежат к какой-либо группе загрузки.

Разработчик службы может определить свою собственную группу загрузки, для чего нужно вставить в подходящей позиции новый элемент в упомянутый выше список групп. Если в конфигурации службы указать группу загрузки, которая не перечислена в списке, то служба будет запущена после того, как запустятся все группы, но до запуска служб, группа загрузки которых не указана.

Зависимости

depends
Рис. 4. Зависимости службы Fax

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

Учетная запись службы

Любой процесс в Windows NT выполняется от лица какого-либо пользователя. Всякий раз, когда один из потоков процесса осуществляет доступ к ресурсу, например, открывая файл или ключ реестра, подсистема безопасности проверяет, имеет ли этот пользователь право доступа к указанному ресурсу. Каждый пользователь идентифицируется своей учетной записью (logon account) в системе, и когда говорят о пользователях в контексте безопасности, на самом деле имеют в виду их учетные записи.

Службы здесь не являются исключением. Создавая процесс службы, SCM осуществляет процедуру входа в систему для учетной записи, указанной в конфигурации службы, и процесс службы выполняется от имени этой учетной записи (к сожалению, очень тяжело подобрать подходящий русскоязычный термин для английского logon, «вход в систему» не вполне точно отражает суть процесса. Для русского человека это словосочетание ассоциируется с действиями конкретного пользователя, в то время как в данном контексте это сугубо программный процесс аутентификации, который может происходить без участия и ведома пользователя). Как уже отмечалось, если несколько служб совместно используют процесс, то всем им должна быть назначена одна и та же учетная запись. В Windows NT 4 и Windows 2000 по большому счету вы имеете выбор из трех вариантов:

Windows XP добавляет еще два пункта в меню:

Мы не будем подробно рассматривать все последствия, которые влечет выбор той или иной учетной записи, поскольку этот вопрос заслуживает отдельной статьи.

Задавая учетную запись для службы, вы должны указать имя пользователя и пароль. Специальные учетные записи, LocalSystem, LocalService и NetworkService, не имеют пароля. Для обычных учетных записей требуется пароль, который менеджер системных служб сохраняет и использует в процедуре входа в систему, которая необходима для создания процесса от имени этой учетной записи. Если пароль задан неверно, это обнаружится только в момент запуска службы, так как именно в этот момент выполняется процедура входа в систему и проверяется пароль.

Действия при сбое

Начиная с Windows 2000, на менеджер системных служб, помимо его основных задач, возложена также задача мониторинга работающих служб. Если процесс службы перестает существовать, не известив менеджер об остановке службы, то такая ситуация считается сбоем службы. SCM ведет счетчик сбоев службы, начиная с загрузки системы, и позволяет ассоциировать определенное действие с каждым сбоем.

Набор действий при сбое определяется структурой SERVICE_FAILURE_ACTIONS :

Система предлагает выбор из четырех действий, которые можно выполнить при сбое службы. Эти действия задаются элементами перечисления SC_ACTION_TYPE :

SC_ACTION_NONE Не выполнять никакого действия
SC_ACTION_REBOOT Перезагрузить систему
SC_ACTION_RESTART Перезапустить службу
SC_ACTION_RUN_COMMAND Запустить указанную программу

Поле Delay структуры SC_ACTION указывает задержку в миллисекундах, которую менеджер системных служб должен сделать, прежде чем выполнять действие. Это полезно главным образом при перезагрузке системы.

Давайте более подробно рассмотрим каждое из возможных действий. Если вы хотите поддержать теорию экспериментом, вы может воспользоваться тестовой службой, которая прилагается к этой статье. Чтобы имитировать сбой службы, достаточно принудительно завершить процесс службы, что можно сделать, например, с помощью утилит из статьи Как принудительно завершить процесс?

Это действие означает автоматический перезапуск службы при сбое. Например, служба удаленного доступа к реестру в Windows 2000 по умолчанию сконфигурирована именно таким образом. И снова подсистема безопасности дает о себе знать: если вы хотите добавить это действие в конфигурацию службы, вы должны открыть handle службы с правом доступа SERVICE_START, помимо SERVICE_CHANGE_CONFIG, которое обычно необходимо для изменения конфигурации.

Как видите, можно задать только одну командную строку на все действия. Это означает, что если в вашем списке действий действие запуска программы встречается несколько раз, например, для первого и второго сбоя, то и для первого, и для второго сбоя будет запущена одна и та же программа. Чтобы позволить программе отличить один сбой от другого, SCM позволяет задать в командной строке метапараметр «%1%». При запуске программы эта последовательность будет заменена номером сбоя.

Например, если вы зададите командную строку как:

то при первом и втором сбоях программа будет вызвана как

соответственно. Таким образом программа сможет определить номер сбоя и предпринять соответствующие действия.

Дескриптор безопасности

Право доступа Описание
SERVICE_QUERY_CONFIG Чтение конфигурации службы с помощью функций QueryServiceConfig и QueryServiceConfig2
SERVICE_CHANGE_CONFIG Изменение конфигурации службы с помощью ChangeServiceConfig и ChangeServiceConfig2
SERVICE_QUERY_STATUS Запрос текущего состояния службы посредством QueryServiceStatus
SERVICE_ENUMERATE_DEPENDENTS Перечисление зависимых служб с помощью функции EnumDependentServices
SERVICE_START Запуск службы с помощью StartService
SERVICE_STOP Остановка службы посредством функции ControlService с кодом управления SERVICE_CONTROL_STOP
SERVICE_PAUSE_CONTINUE Приостановка и возбновление службы с помощью ControlService с кодами управления SERVICE_CONTROL_PAUSE и SERVICE_CONTROL_CONTINUE соответственно
SERVICE_INTERROGATE Требование к службе немедленно доложить о своем статусе с помощью ControlService с кодом SERVICE_CONTROL_INTERROGATE
SERVICE_USER_DEFINED_CONTROL Посылка пользовательских сигналов управления посредством ControlService
DELETE Удаление службы с помощью DeleteService
READ_CONTROL Чтение дескриптора безопасности с помощью QueryServiceObjectSecurity
WRITE_DAC Установка нового списка доступа в дескриптор безопасности с помощью SetServiceObjectSecurity
WRITE_OWNER Смена владельца в дескрипторе безопасности посредством SetServiceObjectSecurity
SERVICE_ALL_ACCESS Эта константа является комбинацией всех перечисленных выше прав доступа.

Таблица 3. Права доступа к системной службе

Everyone (Все) * SERVICE_ENUMERATE_DEPENDENTS
SERVICE_INTERROGATE
SERVICE_QUERY_CONFIG
SERVICE_QUERY_STATUS
SERVICE_USER_DEFINED_CONTROL
READ_CONTROL
System (Система)
Power Users (Опытные пользователи)
SERVICE_ENUMERATE_DEPENDENTS
SERVICE_INTERROGATE
SERVICE_PAUSE_CONTINUE
SERVICE_QUERY_CONFIG
SERVICE_QUERY_STATUS
SERVICE_START
SERVICE_STOP
SERVICE_USER_DEFINED_CONTROL
READ_CONTROL
Administrators (Администраторы)
Server Operators (Операторы сервера) **
SERVICE_ALL_ACCESS

* В Windows 2000 и Windows XP вместо группы Everyone используется группа Authenticated Users (Прошедшие проверку), которая включает всех аутентифицированных пользователей (группа Everyone включает еще и анонимных пользователей).
** Эта группа присутствует только в Windows NT 4.

Функции чтения и изменения конфигурации

Последний параметр задает набор прав доступа, которые требуется получить. Полный список прав доступа к службе был приведен в разделе, посвященном дескриптору безопасности службы.

Задавая этот параметр, всегда нужно указывать именно те флаги доступа, которые действительно необходимы. Это позволит пользоваться вашей программой наиболее широкому кругу пользователей. Например, если вы хотите отображать текущее состояние некоторой службы иконкой на панели задач, но при вызове OpenService указали SERVICE_ALL_ACCESS, то программой, скорее всего, смогут пользоваться только администраторы, поскольку только администраторам по умолчанию разрешен полный доступ к службам. Если бы вы указали только право доступа SERVICE_QUERY_STATUS, которое на самом деле необходимо в данной ситуации, то и обычные пользователи смогли бы воспользоваться этой программой.

QueryServiceConfig

Функция QueryServiceConfig возвращает информацию о конфигурации службы.

Задает handle службы, конфигурационную информацию которой требуется получить. Для успешного выполнения функции, handle должен быть открыт с правом доступа SERVICE_QUERY_CONFIG.

Поля этой структуры говорят сами за себя. Поле lpDependencies содержит указатель на строку, содержащую имена служб и групп загрузки, от которых зависит данная служба,разделенные нулем. Конец списка обозначается двумя идущими подряд нулевыми символами. Чтобы можно было отличить имена служб от имен групп загрузки, перед именами последних ставится символ, задаваемый макросом SC_GROUP_IDENTIFIER, который определен в файле winsvc.h как ‘+’. Например, если некоторая служба зависит от службы RPCSS и группы NetworkDDE, поле lpDependencies будет указывать на такую строку:

Этот параметр является указателем на переменную, в которую функция заносит необходимый размер буфера. Обычно QueryServiceConfig вызывается два раза: первый раз с нулевым размером буфера, чтобы получить необходимый размер, а затем, предварительно выделив буфер необходимого размера, второй раз, чтобы получить конфигурационную информацию. Пример, представленный в конце этого раздела, демонстрирует этот подход.

ChangeServiceConfig

Функция ChangeServiceConfig служит для изменения конфигурации службы.

QueryServiceConfig2

Функция QueryServiceConfig2 позволяет получить дополнительные параметры конфигурации службы, такие как описание и список действий при сбое службы. Эта функция присутствует только в Windows 2000 и более поздних версиях.

Задает handle службы, конфигурационную информацию которой требуется получить. Для успешного выполнения функции, handle должен быть открыт с правом доступа SERVICE_QUERY_CONFIG.

Указывает, какую информацию требуется получить. В настоящее время определены только два значения этого параметра. Не исключено, что в будущих версиях Windows этот набор будет расширен.

SERVICE_CONFIG_DESCRIPTION Требуется получить описание службы
SERVICE_CONFIG_FAILURE_ACTIONS Требуется получить список действий при сбое

Этот параметр является указателем на переменную, в которую функция заносит требуемый размер буфера. В конце этого раздела приведен пример, демонстрирующий использование этого параметра.

ChangeServiceConfig2

Функция ChangeServiceConfig2 позволяет установить описание и список действий при сбое службы.

Задает handle службы, конфигурационную информацию которой требуется изменить. Для успешного выполнения функции, handle должен быть открыт с правом доступа SERVICE_CHANGE_CONFIG. Однако если устанавливается список действий при сбое, включающий перезапуск службы, handle должен быть открыт с правом доступа SERVICE_START.

Кроме того, если для службы на локальном компьютере, устанавливается список действий при сбое, содержащий перезагрузку системы, то в токене вызывающего должна быть включена привилегия SE_SHUTDOWN_NAME.

Указывает тип устанавливаемой информации. Это те же два значения, которые используются вместе с QuerySystemConfig2 :

SERVICE_CONFIG_DESCRIPTION Требуется установить описание службы
SERVICE_CONFIG_FAILURE_ACTIONS Требуется установить список действий при сбое

Ниже приведен пример установки списка действий при сбое службы. Этот фрагмент указывает менеджеру системных служб при первом и втором сбое службы немедленно перезапустить ее, а при возникновении третьего сбоя, перезагрузить компьютер, выдержав паузу в 60 секунд. Помимо этого, фрагмент удаляет командную строку, если она была ранее задана, поскольку поле lpCommand указывает на пустую строку, но оставляет без изменения сообщение, рассылаемое по сети перед перезагрузкой, так как соответствующий параметр установлен в NULL:

Пример: получение конфигурационной информации службы

Как и было обещано, в завершение части статьи, посвященной конфигурации системных служб, мы рассмотрим небольшой пример (см. листинг 2). Это консольное приложение, отображающее конфигурацию службы, имя которой указано в качестве параметра командной строки.

Чтобы не загромождать пример лишними деталями, я решил ограничить части, специфичные для Windows 2000 и более поздних версий, директивами препроцессора, вместо того, чтобы определять версию операционной системы в процессе выполнения и находить соответствующие функции в библиотеке ADVAPI32.DLL.

Продолжение следует

Во второй части статьи мы научимся запускать и останавливать службы, а также рассмотрим вопросы установки системных служб.

Источник


Укажите название процесса (например, sc.exe) из диспетчера задач в окно поиска и определите,
насколько вреден или полезен он для Вашего компьютера.

Неизвестно: sc.exe

Расположение:
Процесс: Windows NT Service Management
Приложение:
Правообладатель: Microsoft
Описание:

sc.exe is a command-line tool which comes bundled with Windows and offers the functionality to maintain and administer Windows NT services. This is a non-essential system process, however should not be terminated unless suspected of causing problems.

Note: sc.exe is an advertising program by Rhombus. This process monitors your browsing habits and distributes the data back to the author’s servers for analysis.
. This process is a security risk and should be removed from your system.
Please see additional details regarding this process.

Перевод: (автоматический)


sc.exe

  • %SYSTEM% (100.00%)
  • 5.1.2600.0 (16.67%)
  • 6.1.7600.16385 (66.67%)
  • 6.3.9600.16384 (16.67%)
Версия Размер в байтах
6.3.9600.16384 59904 (100.00%)
6.1.7600.16385 37376 (25.00%) 45056 (75.00%)
5.1.2600.0 31232 (100.00%)
  • пусто (16.67%)
  • A tool to aid in developing services for WindowsNT (16.67%)
  • Âñïîìîãàòåëüíîå ñðåäñòâî äëÿ ðàçðàáîòêè ñëóæá WindowsNT (16.67%)
  • Ñðåäñòâî íàñòðîéêè äèñïåò÷åðà ñëóæá (16.67%)
  • Вспомогательное средство для разработки служб WindowsNT (33.33%)
  • Microsoft Corporation (100.00%)

Попробуйте найти то же самое в Google

Google

Пользовательского поиска


Полный список процессов (в разработке)
0 1 2 3 4 5 6 7 8 9 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z _

Иногда может потребоваться взять исполняемый файл и зарегистрировать его в качестве службы Windows. Для этого есть несколько способов, я обычно пользуюсь двумя из них.

Sc.exe

Для создания и службы из командной строки можно использовать программу SC (Sc.exe). SC представляет из себя утилиту командной строки, которая реализует вызовы ко всем функциям интерфейса прикладного программирования (API) управления службами Windows. С ее помощью можно производить любые действия со службами —  просматривать состояние, управлять (запускать, останавливать и т.п.), изменять параметры, а также создавать новые службы.

При создании службы с помощью SC нет необходимости вручную создавать записи в реестре и затем перезагружать компьютер, чтобы обеспечить обновление базы данных диспетчером служб. Также SC позволяет указать имя удаленного компьютера, что дает возможность управлять службами как на локальном, так и на удаленном компьютере.

Для создания нового сервиса запускаем команду Sc create. Она создает запись службы в реестре и в базе данных диспетчера служб. Sc create имеет следующий синтаксис:

sc create [ServiceName] [binPath= ] <параметр1= > <параметр2= >

ServiceName — указывает имя, которое будет присвоено разделу службы в реестре. Имейте в виду, что это имя отличается от отображаемого имени службы (имени, которое отображается в оснастке «Services»);
binPath — указывает путь к исполняемому файлу службы.

Для примера создадим службу MyService, укажем отображаемое имя My New Service, зададим тип службы и поставим ее на авто-запуск:

Sc create MyService binPath=C:MyServiceMyService.exe DisplayName=″My New Service″ type=own start=auto

Затем откроем оснастку «Services» и посмотрим результат.

оснастка Службы

Изменять параметры уже созданной службы можно командой Sc config. Например, мне не понравилось отображаемое имя службы и я хочу его изменить:

Sc config MyService DisplayName=″My Service″

Ну и полностью удалить службу можно вот так:

Sc delete MyService

создание, изменение и удаление службы Windows

PowerShell

PowerShell может почти все 🙂 , в том числе и управлять службами Windows. Создать новую службу можно с помощью командлета New-Service. Создадим такой же сервис, как и в предыдущем примере, только добавим к нему описание (Description):

New-Service -Name MyService -BinaryPathName C:MyServiceMyService.exe`
-DisplayName ″My New Service″ -Description ″Very Important Service !!!″

Изменить параметры службы можно командлетом Set-Service:

Set-Service -Name MyService -Description ″Not Very Important Service″ -StartupType Manual

создание и изменение служб с помощью PowerShell

В принципе PowerShell имеет примерно такой же функционал как и Sc.exe, разве что позволяет добавить описание. А вот для удаления служб в PS простого способа нет, придется воспользоваться вот такой конструкцией:

(Get-WmiObject win32_service -Filter ″name=′MyService′″).delete()

Поэтому лично я предпочитаю использовать Sc.exe.

Создание службы Windows с помощью программы Sc.exe

Данный материал является зеркалом статьи сайта http://support.microsoft.com

Для создания служб Windows можно использовать программу Sc.exe, включенную в пакет ресурсов Resource Kit, которая реализует вызовы ко всем функциям интерфейса прикладного программирования (API) управления службами Windows. Настроить параметры для этих функций можно, задав их в командной строке. С помощью средства Sc.exe имеется возможность запросить состояние службы и получить значения, хранящиеся в полях структуры состояний. SC позволяет задавать имя удаленного компьютера, что дает возможность вызвать функции интерфейса API службы и посмотреть структуры состояния службы на удаленном компьютере.

Кроме того, Sc.exe позволяет вызвать любую функцию интерфейса API управления службами и изменить любой параметр, используя командную строку. Данное средство предоставляет удобный способ создания и изменения записей службы в реестре и в базе данных диспетчера служб. Для настройки службы нет необходимости вручную создавать записи в реестре и затем перезагружать компьютер, чтобы обеспечить обновление базы данных диспетчером служб.

Программа Sc.exe использует следующий синтаксис:

Синтаксис 1 (синтаксис 1 используется для запуска Sc.exe)

sc [Servername] Command Servicename [Optionname= Optionvalue…]

Синтаксис 2 (синтаксис 2 используется для просмотра справки, за исключением команды query)

sc [Command]

Параметры

  • Servername
    Необязательный параметр. Задает имя удаленного сервера, на котором будут запускаться команды. Перед именем необходимо поставить две обратные косые черты () (например, \myserver). Чтобы запустить Sc.exe на локальном компьютере, этот параметр следует пропустить.
  • Command
    Задает команду sc. Следует отметить, что для выполнения многих команд sc на определенных компьютерах требуются права администратора. Программа Sc.exe поддерживает следующие команды:

    Config
    Изменяет конфигурацию службы (постоянные параметры).

    Continue
    Посылает службе запрос Continue.

    Control
    Посылает службе запрос Control.

    Create
    Создает службу (добавляет ее в реестр).

    Delete
    Удаляет службу (из реестра).

    EnumDepend
    Перечисляет зависимости служб.

    GetDisplayName
    Указывает отображаемое имя службы.

    GetKeyName
    Указывает имя раздела службы.

    Interrogate
    Посылает службе запрос Interrogate.

    Pause
    Посылает службе запрос Pause.

    qc
    Запрашивает конфигурацию службы. Дополнительные сведения см. в разделе «SC QC».

    Query
    Запрашивает состояние службы или указывает состояние по типам служб. Дополнительные сведения см. в разделе «SC QUERY».

    Start
    Запускает службу.

    Stop
    Посылает службе запрос Stop.

  • Servicename
    Указывает имя, присвоенное разделу службы в реестре. Следует отметить, что это имя отличается от отображаемого имени службы (имени, которое возвращается командой net start и отображается в разделе «Службы» панели управления). Программа Sc.exe использует имя раздела службы в качестве основного идентификатора службы.
  • Optionname
    Параметры «Optionname» и «Optionvalue» служат для указания имен и значений дополнительных параметров. Между именем параметра и знаком равенства нет пробела. Можно указать имя одного или нескольких дополнительных параметров и пары значений, или не указывать их вовсе.
  • Optionvalue
    Задает значение параметра, которому присвоено имя параметром «Optionname». Как правило, диапазон допустимых значений устанавливается отдельно для каждого параметра Optionname. Для получения списка допустимых значений обратитесь за справкой по каждой команде.

Для выполнения ряда команд необходимо иметь права администратора. Следовательно, необходимо обладать правами администратора на компьютере, на котором создается служба.

Команда sc create создает запись службы в реестре и в базе данных диспетчера служб.

Синтаксис

sc [Servername] create Servicename [Optionname=Optionvalue…

Параметры

  • Servername
    Необязательный параметр. Задает имя удаленного сервера, на котором будут запускаться команды. Перед именем необходимо поставить две обратные косые черты (например, \myserver). Чтобы запустить SC на локальном компьютере, этот параметр следует пропустить.
  • Servicename
    Указывает имя, присвоенное разделу службы в реестре. Следует отметить, что это имя отличается от отображаемого имени службы, которое возвращается командой net start и отображается в разделе «Службы» панели управления. Программа Sc.exe использует имя раздела службы в качестве основного идентификатора службы.
  • Optionname
    Параметры «Optionname» и «Optionvalue» служат для указания имен и значений дополнительных параметров. Между именем параметра и знаком равенства нет пробела. Можно указать имя одного или нескольких дополнительных параметров и пары значений, или не указывать их вовсе. Команда sc query поддерживает следующие значения:OptionnameOptionvalue

    type=own, share, interact, kernel, filesys
    Тип службы, которую необходимо создать. Значения параметров включают тип службы, используемый драйверами.
    (по умолчанию = share)

    start=boot, system, auto, demand, disabled
    Тип запуска службы. Значения параметров включают тип запуска, используемый драйверами.
    (по умолчанию = demand)

    error=normal, severe, critical, ignore
    Указывает серьезность ошибки, если служба не запускается при загрузке.
    (по умолчанию = normal)

    binPath=(строка)
    Указывает путь к двоичному файлу службы. Этот параметр не имеет значения по умолчанию; его следует ввести самостоятельно.

    group=(строка)
    Указывает имя группы, членом которой является эта служба. Список групп сохраняется в разделе ServiceGroupOrder реестра.
    (по умолчанию = пустое)

    tag=(строка)
    При выборе значения «yes» Sc.exe получает код TagId из вызова CreateService, однако Sc.exe не отображает этот тег.
    (по умолчанию = пустое)

    depend=(строка с разделителями-пробелами)
    Указывает имена служб и групп, которые должны запускаться перед запуском этой службы.

    obj=(строка)
    Указывает имя учетной записи, для которой будет выполняться служба. Для драйверов — это значение является именем объекта драйвера Windows.
    (по умолчанию = LocalSystem)

    DisplayName=(строка)
    Указывает имя службы, которое используется в программах пользовательского интерфейса.

    password=(строка)
    Задает пароль. Данный параметр требуется для использования любой учетной записи, за исключением «Локальная система».

Optionvalue
Задает значение параметра, которому присвоено имя параметром «Optionname». Список допустимых значений см. в справке к параметру «Optionname». При вводе пустых кавычек передается пустая строка.

Примечание. Команда sc create выполняет операции функции CreateService интерфейса API.

Далее приведен пример создания записи реестра для службы с именем «NewService» на компьютере \remotecomputer:

sc \remotecomputer create newservice binpath= c:ntsystem32newserv.exe

По умолчанию создается служба типа WIN32_SHARE_PROCESS с типом запуска SERVICE_DEMAND_START. Она не имеет никаких зависимостей и выполняется в контексте безопасности LocalSystem.

Далее приведен пример создания службы на локальном компьютере, которая запускается автоматически и выполняется в собственном процессе. Она содержит зависимости от группы TDI и службы NetBIOS. Список зависимостей с разделителями-пробелами необходимо заключить в кавычки.

sc create newservice binpath= c:ntsystem32newserv.exe type= own start= auto depend= «+tdi netbios»

Дополнительные сведения о программе Sc.exe см. в файле Sc-dev.txt, который включен в пакет ресурсов Resource Kit. Этот файл содержит подробное описание Sc.exe.

Обновлено 24.10.2013 11:01

Служба Windows NT (Windows NT service) — специальный процесс, обладающий унифицированным интерфейсом для взаимодействия с операционной системой Windows NT. Службы делятся на два типа — службы Win32, взаимодействующие с операционной системой посредством диспетчера управления службами (Service Control Manager — SCM), и драйвера, работающие по протоколу драйвера устройства Windows NT. Далее в этой статье мы будем обсуждать только службы Win32.

Одним из важнейших свойств службы является неинтерактивность. Типичное «поведение» службы — это незаметная для обычного пользователя работа в фоновом режиме. В силу этого службы наиболее подходят для реализации следующих типов приложений:

От обычного приложения Win32 службу отличают 3 основных свойства. Рассмотрим каждое из них.

Во-первых, это возможность корректного останова (приостанова) работы службы. Пользователь или другое приложение, использующие стандартные механизмы, имеют возможность изменить состояние службы — перевести ее из состояния выполнения в состояние паузы или даже остановить ее работу. При этом служба перед изменением своего состояния получает специальное уведомление, благодаря которому может совершить необходимые для перехода в новое состояние действия, например, освободить занятые ресурсы.

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

И, наконец, возможность работы в произвольном контексте безопасности. Контекст безопасности Windows NT определяет совокупность прав доступа процесса к различным объектам системы и данным. В отличие от обычного приложения Win32, которое всегда запускается в контексте безопасности пользователя, зарегистрированного в данный момент в системе, для службы контекст безопасности ее выполнения можно определить заранее. Это означает, что для службы можно определить набор ее прав доступа к объектам системы заранее и тем самым ограничить сферу ее деятельности. Применительно к службам существует специальный вид контекста безопасности, используемый по умолчанию и называющийся Local System. Служба, запущенная в этом контексте, обладает правами только на ресурсы локального компьютера. Никакие сетевые операции не могут быть осуществлены с правами Local System, поскольку этот контекст имеет смысл только на локальном компьютере и не опознается другими компьютерами сети.

Любое приложение, имеющее соответствующие права, может взаимодействовать со службой. Взаимодействие, в первую очередь, подразумевает изменение состояния службы, то есть перевод ее в одно из трех состояний — работающее (Запуск), приостанов (Пауза), останов и осуществляется при помощи подачи запросов SCM. Запросы бывают трех типов — сообщения от служб (фиксация их состояний), запросы, связанные с изменением конфигурации службы или получением информации о ней и запросы приложений на изменение состояния службы.

Для управления службой необходимо в первую очередь получают ее дескриптор с помощью функции Win32 API OpenService. Функция StartService запускает службу. При необходимости изменение состояния службы производится вызовом функции ControlService.

Информация о каждой службе хранится в реестре — в ключе HKLMSYSTEMCurrentControlSetServicesServiceName. Там содержатся следующие сведения:

Приложения, которым требуется получить информацию о какой-либо службе или изменить тот или иной параметр службы, по сути должны изменить информацию в базе данных службы в реестре. Это можно сделать посредством соответствующих функций Win32 API:

Для того, чтобы «быть службой», приложение должно быть устроено соответствующим образом, а именно — включать в себя определенный набор функций (в терминах C++) с определенной функциональностью. Рассмотрим кратко каждую из них.

Функция main

Как известно функция main — точка входа любого консольного Win32 приложения. При запуске службы первым делом начинает выполняться код этой функции. Втечение 30 секунд с момента старта функция main должна обязательно вызвать StartServiceCtrlDispatcher для установления соединения между приложением и SCM. Все коммуникации между любой службой данного приложения и SCM осуществляются внутри функции StartServiceCtrlDispatcher, которая завершает работу только после остановки всех служб в приложении.

Функция ServiceMain

Помимо общепроцессной точки входа существует еще отдельная точка входа для каждой из служб, реализованных в приложении. Имена функций, являющихся точками входа служб (для простоты назовем их всех одинаково — ServiceMain), передаются SCM в одном из параметров при вызове StartServiceCtrlDispatcher. При запуске каждой службы для выполнения ServiceMain создается отдельный поток.

Получив управление, ServiceMain первым делом должна зарегистрировать обработчик запросов к службе, функцию Handler, свою для каждой из служб в приложении. После этого в ServiceMain обычно следуют какие-либо действия для инициализации службы — выделение памяти, чтение данных и т.п. Эти действия должны обязательно сопровождаться уведомлениями SCM о том, что служба все еще находится в процессе старта и никаких сбоев не произошло. Уведомления посылаются при помощи вызовов функции SetServiceStatus. Все вызовы, кроме самого последнего должны быть с параметром SERVICE_START_PENDING, а самый последний — с параметром SERVICE_RUNNING. Периодичность вызовов определяется разработчиком службы, исходя их следующего условия: продолжительность временного интервала между двумя соседними вызовами SetServiceStatus не должна превышать значения параметра dwWaitHint, переданного SCM при первом из двух вызовов. В противном случае SCM, не получив во-время очередного уведомления, принудительно остановит службу. Такой способ позволяет избежать ситуации «зависания» службы на старте в результате возникновения тех или иных сбоев (вспомним, что службы обычно неинтерактивны и могут запускаться в отсутствие пользователя). Обычная практика заключается в том, что после завершения очередного шага инициализации происходит уведомление SCM.

Функция Handler

Как уже упоминалось выше, Handler — это прототип callback-функции, обработчика запросов к службе, своей для каждой службы в приложении. Handler вызывается, когда службе приходит запрос (запуск, приостанов, возобновление, останов, сообщение текущего состояния) и выполняет необходимые в соответствии с запросом действия, после чего сообщает новое состояние SCM.

Один запрос следует отметить особо — запрос, поступающий при завершении работы системы (Shutdown). Этот запрос сигнализирует о необходимости выполнить деинициализацию и завершиться. Microsoft утверждает, что для завершения работы каждой службе выделяется 20 секунд, после чего она останавливается принудительно. Однако тесты показали, что это условие выполняется не всегда и служба принудительно останавливается до истечения этого промежутка времени.

Система безопасности служб

Любое действие над службами требует наличия соответствующих прав у приложения. Все приложения обладают правами на соединение с SCM, перечисление служб и проверку заблокированности БД службы. Регистрировать в сиситеме новую службу или блокировать БД службы могут только приложения, обладающие административными правами.

Каждая служба имеет дескриптор безопасности, описывающий какие пользователи имеют права на ту или иную операцию. По умолчанию:

  • Все пользователи имеют права SERVICE_QUERY_CONFIG, SERVICE_QUERY_STATUS, SERVICE_ENUMERATE_DEPENDENTS, SERVICE_INTERROGATE и SERVICE_USER_DEFINED_CONTROL;
  • Пользователи, входящие в группу Power Users и учетная запись LocalSystem дополнительно имеют права SERVICE_START, SERVICE_PAUSE_CONTINUE и SERVICE_STOP;
  • Пользователи, входящие в группы Administrators и System Operators имеют право SERVICE_ALL_ACCESS.

Службы и интерактивность

По умолчанию интерактивные службы могут выполняться только в контексте безопасности LocalSystem. Это связано с особенностями вывода на экран монитора в Windows NT, где существует, например, такой объект как “Desktop”, для работы с которым нужно иметь соответствующие права доступа, которых может не оказаться у произвольной учетной записи, отличной от LocalSystem. Несмотря на то, что в подавляющем большинстве случаев это ограничение несущественно однако иногда существует необходимость создать службу, которая выводила бы информацию на экран монитора и при этом выполнялась бы в контексте безопасности отличном от LocalSystem, например, серверная компонента приложения для запуска приложений на удаленном компьютере.

Фрагмент кода из Примера 1. иллюстрирует такую возможность.

В этом фрагменте в ответ на запрос, посланный клиентской частью приложения последством RPC, служба выводит текстовое сообщение на экран монитора.

Пример службы (ключевые фрагменты)

Рассмотрим на примере ключевые фрагменты приложения на языке С++, реализующего службу Windows NT. Для наглядности несущественные части кода опущены.

Функция main

В Примере 2. показан код функции main.

Функция ServiceMain

Особенностью кода, содержащегося в ServiceMain, является то, что часто невозможно заранее предсказать время выполнения той или иной операции, особенно, если учесть, что ее выполнение происходит в операционной системе с вытесняющей многозадачностью. Если операция продлится дольше указанного в параметре вызова SetServiceStatus интервала времени, служба не сможет во-время отправить следующее уведомление, в результате чего SCM остановит ее работу. Примерами потенциально «опасных» операций могут служить вызовы функций работы с сетью при больших таймаутах или единовременное чтение большого количества информации с медленного носителя. Кроме того, такой подход совершенно не применим при отладке службы, поскольку выполнение программы в отладчике сопровождается большими паузами, необходимыми разработчику.

Для преодоления этой проблемы все операции по взаимодействию с SCM следует выполнять в отдельном потоке, не зависящем от действий, происходящих на этапе инициализации.

В Примере 3. показан алгоритм корректного запуска службы, использующий вспомогательный поток.

Функция Handler

В Примере 4. показан код функции Handler и вспомогательных потоков. Для запросов “Stop” и “Shutdown” используется алгоритм корректного останова службы, аналогичный тому, который используется при старте службы, с той лишь разницей, что вместо параметра SERVICE_START_PENDING в SetserviceStatus передается параметр SERVICE_STOP_PENDING, а вместо SERVICE_RUNNING — SERVICE_STOPPED.

В идеале для запросов “Pause” и “Continue” тоже следует использовать этот подход. Любознательный читатель без труда сможет реализовать его, опираясь на данные примеры.

Заключение

В заключение хотелось бы отметить, что с переходом на Windows NT 2000 разработка служб не претерпела изменений. Службы по-прежнему остаются важной частью программного обеспечения на платформе Windows, что предоставляет разработчикам широкое поле деятельности.

Пример 1

// Функция, аналог MessageBox Win32 API
int ServerMessageBox(RPC_BINDING_HANDLE h, LPSTR lpszText,
 LPSTR lpszTitle, UINT fuStyle) 
{ 
  DWORD dwThreadId; 
  HWINSTA hwinstaSave; 
  HDESK hdeskSave; 
  HWINSTA hwinstaUser; 
  HDESK hdeskUser; 
  int result; 
 
  // Запоминаем текущие объекты “Window station” и “Desktop”.
  GetDesktopWindow(); 
  hwinstaSave = GetProcessWindowStation(); 
  dwThreadId = GetCurrentThreadId(); 
  hdeskSave = GetThreadDesktop(dwThreadId); 
 
  // Меняем контекст безопасности на тот, 
  // который есть у вызавшего клиента RPC
  // и получаем доступ к пользовательским 
  // объектам “Window station” и “Desktop”.
  RpcImpersonateClient(h); 
  hwinstaUser = OpenWindowStation(“WinSta0”, 
                FALSE, MAXIMUM_ALLOWED); 
  if (hwinstaUser == NULL) 
  { 
    RpcRevertToSelf(); 
    return 0; 
  } 
  SetProcessWindowStation(hwinstaUser); 
  hdeskUser = OpenDesktop(“Default”, 0, FALSE, MAXIMUM_ALLOWED);
  RpcRevertToSelf(); 
  if (hdeskUser == NULL) 
  { 
    SetProcessWindowStation(hwinstaSave); 
    CloseWindowStation(hwinstaUser); 
    return 0; 
  } 
  SetThreadDesktop(hdeskUser); 
 
  // Выводим обычное текстовое окно.
  result = MessageBox(NULL, lpszText, lpszTitle, fuStyle); 

  // Восстанавливаем сохраненные объекты 
  // “Window station” и “Desktop”.
  SetThreadDesktop(hdeskSave); 
  SetProcessWindowStation(hwinstaSave); 
  CloseDesktop(hdeskUser); 
  CloseWindowStation(hwinstaUser); 
 
  return result; 
}

Пример 2

void main()
{
  SERVICE_TABLE_ENTRY steTable[] = 
  {
    {SERVICENAME, ServiceMain},
    {NULL, NULL}
  };

  // Устанавливаем соединение с SCM. Внутри этой функции
  // происходит прием и диспетчеризация запросов.
  StartServiceCtrlDispatcher(steTable);
}

Пример 3

void WINAPI ServiceMain(DWORD dwArgc, LPSTR *psArgv)
{
  // Сразу регистрируем обработчик запросов.
  hSS = RegisterServiceCtrlHandler(SERVICENAME, ServiceHandler);

  sStatus.dwCheckPoint = 0;
  sStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP |
 SERVICE_ACCEPT_PAUSE_CONTINUE;	
  sStatus.dwServiceSpecificExitCode = 0;
  sStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
  sStatus.dwWaitHint = 0;
  sStatus.dwWin32ExitCode = NOERROR;
	
  // Для инициализации службы вызывается функция InitService();
  // Для того, чтобы в процессе инициализации система не
  // выгрузила службу, запускается поток, который раз в 
  // секунду сообщает, что служба в процессе инициализации. 
  // Для синхронизации потока создаётся событие.
  // После этого запускается рабочий поток, для 
  // синхронизации которого также
  // создаётся событие.

  hSendStartPending = CreateEvent(NULL, TRUE, FALSE, NULL);

  HANDLE hSendStartThread;
  DWORD dwThreadId;
	
  hSendStartThread = CreateThread(NULL, 0, SendStartPending,
  NULL, 0, &dwThreadId);
	
  //Здесь производится вся инициализация службы.
  InitService();

  SetEvent(hSendStartPending);

  if(
    WaitForSingleObject(hSendStartThread, 2000) 
  != WAIT_OBJECT_0) 
  {
    TerminateThread(hSendStartThread, 0);
  }

  CloseHandle(hSendStartPending);
  CloseHandle(hSendStartThread);

  hWork = CreateEvent(NULL, TRUE, FALSE, NULL);

  hServiceThread = CreateThread(NULL, 0, ServiceFunc, 
  0, 0, &dwThreadId);

  sStatus.dwCurrentState = SERVICE_RUNNING;

  SetServiceStatus(hSS, &sStatus);
}

// Функция потока, каждую секунду посылающая уведомления SCM
// о том, что процесс инициализации идёт. Работа функции
// завершается, когда устанавливается 
// событие hSendStartPending.

DWORD WINAPI SendStartPending(LPVOID)
{
  sStatus.dwCheckPoint = 0;
  sStatus.dwCurrentState = SERVICE_START_PENDING;
  sStatus.dwWaitHint = 2000;

  // “Засыпаем” на 1 секунду. Если через 1 секунду 
  // событие hSendStartPending не перешло
  // в сигнальное состояние (инициализация службы не 
  // закончилась), посылаем очередное уведомление, 
  // установив максимальный интервал времени
  // в 2 секунды, для того, чтобы был запас времени до
  // следующего уведомления. 
  while (true)
  {		
    SetServiceStatus(hSS, &sStatus);
    sStatus.dwCheckPoint++;		
    if(WaitForSingleObject(hSendStartPending, 
         1000)!=WAIT_TIMEOUT)
      break;
  }

  sStatus.dwCheckPoint = 0;
  return 0;
}

// Функция, инициализирующая службу. Чтение данных,
// распределение памяти и т.п.
void InitService()
{
  ...
}

// Функция, содержащая «полезный» код службы.
DWORD WINAPI ServiceFunc(LPVOID)
{
  while (true)
  {
    if (!bPause)
    {
      // Здесь содержится код, который как правило 
      // выполняет какие-либо циклические операции...
    }

    if (WaitForSingleObject(hWork, 1000)!=WAIT_TIMEOUT)
      break;
  }

  return 0;
}

Пример 4

// Обработчик запросов от SCM
void WINAPI ServiceHandler(DWORD dwCode)
{
  switch (dwCode)
  {
    case SERVICE_CONTROL_STOP:
    case SERVICE_CONTROL_SHUTDOWN:
      ReportStatusToSCMgr(SERVICE_STOP_PENDING, 
                           NO_ERROR, 0, 1000);
      hSendStopPending = CreateEvent(NULL, TRUE, FALSE, NULL);
      hSendStopThread  = CreateThread(NULL, 0, 
                SendStopPending, NULL, 0, & dwThreadId);
      SetEvent(hWork);
      if (WaitForSingleObject(hServiceThread,
                     1000) != WAIT_OBJECT_0)
      {
        TerminateThread(hServiceThread, 0);
      }
      SetEvent(hSendStopPending);
      CloseHandle(hServiceThread);
      CloseHandle(hWork);
      if(WaitForSingleObject(hSendStopThread,
                       2000) != WAIT_OBJECT_0) 
      {
        TerminateThread(hSendStopThread, 0);
      }
      CloseHandle(hSendStopPending);

      sStatus.dwCurrentState = SERVICE_STOPPED;
      SetServiceStatus(hSS, &sStatus);
      break;
    case SERVICE_CONTROL_PAUSE:
      bPause = true;
      sStatus.dwCurrentState = SERVICE_PAUSED;
      SetServiceStatus(hSS, &sStatus);
      break;
    case SERVICE_CONTROL_CONTINUE:
      bPause = true;
      sStatus.dwCurrentState = SERVICE_RUNNING;
      SetServiceStatus(hSS, &sStatus);
      break;
    case SERVICE_CONTROL_INTERROGATE:
      SetServiceStatus(hSS, &sStatus);
      break;
    default:
      SetServiceStatus(hSS, &sStatus); 
      break;
  }
}


// Функция потока, аналогичная SendStartPending 
// для останова службы.
DWORD WINAPI SendStopPending(LPVOID)
{
  sStatus.dwCheckPoint = 0;
  sStatus.dwCurrentState = SERVICE_STOP_PENDING;
  sStatus.dwWaitHint = 2000;

  while (true)
  {		
    SetServiceStatus(hSS, &sStatus);
    sStatus.dwCheckPoint++;		
    if(WaitForSingleObject(hSendStopPending, 
                         1000)!=WAIT_TIMEOUT)
      break;
  }

  sStatus.dwCheckPoint = 0;
  return 0;
}

Понравилась статья? Поделить с друзьями:
  • Всплывающие черные окна в windows 10
  • Всплывающие окна в windows 10 с правой стороны
  • Всплывающие напоминания на рабочий стол windows 10
  • Всплывающие иконки на рабочем столе windows 10
  • Всплывающая подсказка в microsoft windows это