Программирование для Windows NT© Александр Фролов, Григорий ФроловТом 27, часть 2, М.: Диалог-МИФИ, 1996, 272 стр. Управление сервисамиВы можете создать приложение или сервис, управляющее сервисами. В этом разделе мы рассмотрим основные функции программного интерфейса WIN32, предназначенные для управления сервисами. Более подробную информацию вы найдете в документации SDK. Получение идентификатора системы управления сервисамиИдентификатор системы управления сервисами нужен для выполнения различных операций над сервисами, таких например, как установка сервиса. Вы можете получить этот идентификатор с помощью функции OpenSCManager: SC_HANDLE OpenSCManager( LPCTSTR lpszMachineName, // адрес имени рабочей станции LPCTSTR lpszDatabaseName, // адрес имени базы данных DWORD fdwDesiredAccess); // нужный тип доступа Задавая имя рабочей станции через параметр lpszMachineName, вы можете получить идентификатор системы управления сервисами на любом компьютере сети. Для локального компьютера необходимо указать значение NULL. Для наших примеров параметр lpszDatabaseName, определяющий имя базы данных системы управления сервисами, нужно указать как NULL. При этом по умолчанию будет использована база данных активных сервисов ServicesActive. Через параметр fdwDesiredAccess нужно задать требуемый тип доступа. Здесь можно использовать следующие константы:
Ниже мы привели пример вызова функции OpenSCManager: schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); После использования вы должны закрыть идентификатор, полученный от функции OpenSCManager. Для этого необходимо вызвать функцию CloseServiceHandle: CloseServiceHandle(schSCManager); Установка сервисаДля установки сервиса в систему вы должны использовать функцию CreateService, которая вносит все необходимые дополнения в регистрационную базу данных. Прототип функции CreateService мы привели ниже: SC_HANDLE CreateService( SC_HANDLE hSCManager, // идентификатор базы данных системы // управления сервисами LPCTSTR lpServiceName, // имя сервиса, которое будет использовано // для запуска LPCTSTR lpDisplayName, // имя сервиса для отображения DWORD dwDesiredAccess, // тип доступа к сервису DWORD dwServiceType, // тип сервиса DWORD dwStartType, // способ запуска сервиса DWORD dwErrorControl, // действия при ошибках в момент запуска LPCTSTR lpBinaryPathName, // путь к загрузочному файлу сервиса LPCTSTR lpLoadOrderGroup, // имя группы порядка загрузки LPDWORD lpdwTagId, // адрес переменной для сохранения // идентификатора тега LPCTSTR lpDependencies, // адрес массива имен взаимосвязей LPCTSTR lpServiceStartName, // адрес имени пользователя, права // которого будут применены для работы сервиса LPCTSTR lpPassword ); // адрес пароля пользователя Через параметр hSCManager вы должны передать функции CreateService идентификатор базы данных системы управления сервисами, полученный от функции OpenSCManager, описанной выше. Через параметры lpServiceName и lpDisplayName задаются, соответственно, имя сервиса, которое будет использовано для запуска и имя сервиса для отображения в списке установленных сервисов. С помощью параметра dwDesiredAccess вы должны указать тип доступа, разрешенный при обращении к данному сервису. Здесь вы можете указать следующие значения:
Через параметр dwServiceType необходимо передать тип сервиса. Здесь вы можете указывать те же самые флаги, что и в поле dwServiceType структуры SERVICE_STATUS, описанной выше:
В параметре dwStartType указывается один из следующих способов запуска сервиса:
Параметр dwErrorControl задает действия, выполняемые при обнаружении ошибки в момент загрузки сервиса. Здесь можно указывать одно из следующих значений:
В параметре lpBinaryPathName вы должны указать полный путь к загрузочному файлу сервиса. Через параметр lpLoadOrderGroup передается указатель на имя группы порядка загрузки сервиса. Сделав сервис членом одной из групп порядка загрузки, вы можете определить последовательность загрузки вашего сервиса относительно других сервисов. Список групп порядка загрузки находится в регистрационной базе данных: HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\ServiceGroupOrder Если относительный порядок загрузки не имеет значения, укажите для параметра lpLoadOrderGroup значение NULL. Параметр lpdwTagId используется только в том случае, если значение параметра lpLoadOrderGroup не равно NULL. Параметр lpDependencies должен содержать указатель на массив строк имен сервисов или групп порядка загрузки, которые должны быть запущены перед запуском данного сервиса. Последняя строка такого массива должна быть закрыта двумя двоичными нулями. Если зависимостей от других сервисов нет, для параметра lpDependencies можно указать значение NULL. Последние два параметра функции lpServiceStartName и lpPassword указывают, соответственно, имя и пароль пользователя, с правами которого данный сервис будет работать в системе (имя указывается в форме “ИмяДомена\имяПользователя”). Если параметр lpServiceStartName указан как NULL, сервис подключится к системе как пользователь LocalSystem. При этом параметр lpPassword должен быть указан как NULL. Ниже мы привели фрагмент исходного текста приложения, в котором выполняется установка сервиса из каталога c:\ntbk2\src\service\small\debug: schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); schService = CreateService( schSCManager, MYServiceName, MYServiceName, SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, "c:\\ntbk2\\src\\service\\small\\debug\\small.exe", NULL, NULL, "", NULL, NULL); CloseServiceHandle(schSCManager); Получение идентификатора сервисаДля выполнения операций с сервисом вы должны получить его идентификатор. Это нетрудно сделать с помощью функции OpenService, прототип которой мы привели ниже: SC_HANDLE OpenService( SC_HANDLE schSCManager, // идентификатор базы данных системы // управления сервисами LPCTSTR lpszServiceName, // имя сервиса DWORD fdwDesiredAccess); // тип доступа к сервису Через параметр schSCManager вы должны передать функции OpenService идентификатор базы данных системы управления сервисами, полученный от функции OpenSCManager. Параметр lpszServiceName определяет имя сервиса, а параметр fdwDesiredAccess - желаемый тип доступа к сервису. Выдача команд сервисуПриложение или сервис может выдать команду сервису, вызвав функцию ControlService: BOOL ControlService( SC_HANDLE hService, // идентификатор сервиса DWORD dwControl, // код команды LPSERVICE_STATUS lpServiceStatus); // адрес структуры состояния // сервиса SERVICE_STATUS В качестве кода команды вы можете указать один из следующих стандартных кодов:
Дополнительно вы можете указывать коды команд, определенные вами. Они должны находиться в интервале значений от 128 до 255. Удаление сервиса из системыДля удаления сервиса из системы используется функция DeleteService. В качетсве единственного параметра этой функции необходимо передать идентификатор сервиса, полученный от функции OpenService. Ниже мы привели фрагмент приложения, удаляющий сервис с именем MYServiceName из системы: schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); schService = OpenService( schSCManager, MYServiceName, SERVICE_ALL_ACCESS); ControlService(schService, SERVICE_CONTROL_STOP, &ss); DeleteService(schService); CloseServiceHandle(schSCManager); Заметим, что перед удалением мы останавливаем сервис. Запуск сервисаДля запуска сервиса вы должны использовать функцию StartService: BOOL StartService( SC_HANDLE schService, // идентификатор сервиса DWORD dwNumServiceArgs, // количество аргументов LPCTSTR *lpszServiceArgs); // адрес массива аргументов Через параметр schService вы должны передать функции StartService идентификатор сервиса, полученный от функции OpenService. Параметры dwNumServiceArgs и lpszServiceArgs определяют, соответственно, количество аргументов и адрес массива аргументов, которые получит функция точки входа сервиса. Эти параметры могут использоваться в процессе инициализации. Ниже мы привели фрагмент исходного текста приложения, выполняющий запуск сервиса: schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); schService = OpenService( schSCManager, MYServiceName, SERVICE_ALL_ACCESS); StartService(schService, 0, NULL); CloseServiceHandle(schSCManager); Остановка сервисаОстановка сервиса выполняется посылкой сервису команды SERVICE_CONTROL_STOP, для чего эта комнда передается функции ControlService XE "ControlService" : ControlService(schService, SERVICE_CONTROL_STOP, &ss); Определение конфигурации сервисаПриложение или сервис может определить конфигурацию заданного сервиса, вызвав для этого функцию QueryServiceConfig XE "QueryServiceConfig" : BOOL QueryServiceConfig( SC_HANDLE schService, // идентификатор сервиса LPQUERY_SERVICE_CONFIG lpqscServConfig, // адрес структуры // QUERY_SERVICE_CONFIG, в которую будет // записана конфигурация сервиса DWORD cbBufSize, // размер буфера для записи конфигурации LPDWORD lpcbBytesNeeded); // адрес переменной, в котоую будет // записан размер буфера, необходимый для // сохранения всей информации о конфигурации Формат структуры QUERY_SERVICE_CONFIG приведен ниже: typedef struct _QUERY_SERVICE_CONFIG { DWORD dwServiceType; DWORD dwStartType; DWORD dwErrorControl; LPTSTR lpBinaryPathName; LPTSTR lpLoadOrderGroup; DWORD dwTagId; LPTSTR lpDependencies; LPTSTR lpServiceStartName; LPTSTR lpDisplayName; } QUERY_SERVICE_CONFIG, LPQUERY_SERVICE_CONFIG; Содержимое полей этой структуры соответствует содержимому параметров функции CreateService, описанной ранее. Ниже расположен фрагмент кода, в котором определяется текущая конфигурация сервиса: schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); schService = OpenService( schSCManager, MYServiceName, SERVICE_ALL_ACCESS); lpBuf = (LPQUERY_SERVICE_CONFIG)malloc(4096); if(lpBuf != NULL) { QueryServiceConfig(schService, lpBuf, 4096, &dwBytesNeeded); . . . free(lpBuf); } |