Параметр dwControlsAccepted визначає коди керування, які служба сприймає і обробляє в своєму обробнику керування. Можливі значення перераховані в таблиці 5; декілька значень можуть об’єднуватися порозрядним „або”. Приведена нижче версія serverSK для служби сприймає всі три значення. Додаткові значення описані в документації MSDN.
Таблиця 5. Коди керування, які сприймаються службою
Значення | Дія |
SERVICE_ACCEPT_STOP | Дозволяється SERVICE_CONTROL_STOP |
SERVICE_ACCEPT_PAUSR_CONTINUE | Дозволяється SERVICE_CONTROL_PAUSE і SERVICE_CONTROL_CONTINUE |
SERVICE_ACCEPT_SHUTDOWN (функція ControlService не може видавати цей код керування) | Служба повідомляє, коли система закінчує роботу. Таким чином, система може послати службі значення SERVICE_CONTROL_ SHUTDOWN |
Код служби
Коли обробник зареєстрований і встановлений стан служби SERVICE_START_PENDING, служба може ініціалізувати себе і встановити стан знову. В прикладі перетворення serverSK після того, як сокети ініціалізовані і сервер буде готовий до прийому клієнтів, слідує встановити стан SERVICE_RUNNING.
Обробник керування служби
|
|
Обробник керування служби, який вказаний в функції RegisterServiceCtrlHandler, має наступну форму:
VOID WINAPI ServerCtrlHandler (DWORD fdwControl)
Єдиний параметр цієї функції, fdwControl, містить сигнал керування, який передається диспетчером SCM для обробки. Таким чином, обробник керування є узагальненою формою обробника керування консолі.
Сигнали керування можуть мати слідуючи значення:
SERVICE_CONTROL_STOP
SERVICE_CONTROL_PAUSE
SERVICE_CONTROL_CONTINUE
SERVICE_CONTROL_INTERROGATE
SERVICE_CONTROL_SHUTDOWN
Також допускаються значення користувача в діапазоні 128-255, але тут вони не розглядаються.
Обробник викликається диспетчером SCM в тому ж потоці, що і головна програма, і звичайно будується на базі оператора switch.
Керування службами Windows NT
Наступна задача після написання коду – передача служби під керуванням SCM, щоб її можна було запускати, закінчувати і виконувати інші керуючі операції.
Для цього потрібно виконати декілька дій з відкриття SCM, створення служби під керуванням SCM і потім з її запуску. Ці дії не керують службою безпосередньо; вони представляють собою команди для SCM, який працює з вказаною службою.
Відкриття SCM
Для створення служби необхідний окремий процес, який грає роль „адміністратора”. Перша дія – відкриття SCM і отримання дескриптору, який потім дозволяє створити службу.
SC_HANDLE OpenSCManager (
LPCTSTR lpMachineName,
LPCTSTR lpDatabaseName,
DWORD dwDesiredAddress)
Параметри
lpMachineName рівний NULL, якщо SCM знаходиться в локальній системі, хоча можна звертатися до SCM і на інших машинах в мережі.
lpDatabaseName – також звичайно NULL.
dwDesiredAddress – звичайно SC_MANAGER_ALL_ACCESS, але можна задати більш обмежені права доступу, як описано в вбудованій документації.
|
|
Створення і видалення служби
Нові служби фіксуються в слідую чому розділі системного реєстру:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services
Для створення служби слідує визвати функцію Create Service, вказавши дескриптор SC_HANDLE, отриманий при виклику OpenSCManager.
SC_HANDLE CreatrService (
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 – дескриптор SC_HANDLE, який отриманий від OpenSCManager.
lpServiceName – ім’я, по якому в подальшому ми будемо посилатися на службу, це одне із імен логічних служб, які вказані в таблиці при виклику StartServiceCtrlDispatcher. Замітимо, що для кожної логічної служби потрібний окремий виклик CreateService.
lpDisplayName – ім’я, під яким служба буде відображатися в реєстрі і в аплеті Служби, який відкривається на панелі керування в розділі Средства адміністрування. Це ім’я з’являється зразу після успішного виклику CreateService.
dwDesiredAccess може мати значення SERVICE_ALL_ACCESS або бути комбінацією GENERIC_READ, GENERIC_WRITE і GENERIC_EXECUTE. Більш детально це описано в вкладеній документації.
dwServiceType має значення, які представленні в таблиці 1.
dwStartType визначає порядок запуску служби. В наших прикладах використовується зачення SERVICE_DEMAND_START; інші значення (SERVICE_BOOT_START і SERVICE_SYSTEM_START) дозволяють запускати служби драйверів пристроїв в ході початкового запуску системи, а SERVICI_AUTO_START визначає, що служба повинна автоматично запускатися при запуску системи.
lpBinaryPathName вказує на виконуючий файл служби; розширення.exe вказувати не потрібно.
Інші параметри визначають ім’я облікового запису і пароль, групи для об’єднувальних служб і залежності в випадку декількох взаємозалежних служб.
Для отримання дескриптора іменованої служби використовується функція OpenService, для видалення служби із системного реєстру – DeleteService, а для закриття дескриптора – CloseServiceHandle.
Запуск служби
Зразу після створення служба ще не працює. Запустіть функцію ServiceMain (), вказавши дескриптор, який отриманий від CreateService, і параметри командного рядка argc, argv, які вимагає „головна” функція служби (тобто функція, яка вказана в таблиці служб).
BOOL StartService (
SC_HANDLE hService,
DWORD argc,
LPTSTR argv [])
Керування служби
Для керуючої дії над службою диспетчером SCM повинен бути викликаний обробник керування службою з відповідним кодом керування.
BOOL ControlService (
SC_HANDLE hService,
DWORD ControlCode,
LPSERVICE_STATUS pServStat)
Якщо доступ дозволений, ControlCode має одне із наступних значень:
SERVICE_CONTROL_STOP
SERVICE_CONTROL_PAUSE
SERVICE_CONTROL_CONTINUE
SERVICE_CONTROL_INTERROGATE
SERVICE_CONTROL_SHUTDOWN
або вказане користувачем значення в діапазоні 128-255. Це ті ж значення, які використовувалися для прапора fdwControl в функції ServerCtrlHandler.
pServStat вказує на структуру SERVICE_STATUS, яка отримує поточний стан. Ця ж структура, що використовується в функції SetServiceStatus.