Програмування служб windows 7 з тригерами (ч

Ми вважаємо за краще вважати служби запущеними завданнями, які працюють у фоновому режимі і не зачіпають операції користувача. Служби в Windows відповідають за всі види фонової активності, починаючи зі служби Remote Procedure Call (RPC), Printer Spooler і аж до служби Network Location Awareness.

По-друге, ці витратні ресурси безпосередньо позначаються на споживанні електроенергії. Чим більше навантаження ми даємо на ЦП, тим більше електроенергії комп'ютер споживає. Це може бути критично важливо для ноутбуків і може скоротити час роботи батареї на кілька годин.

По-третє, постійна робота непродуктивного програмного забезпечення може призвести до витоку пам'яті і загальної нестабільності системи. Це може привести до збою в роботі програми, але, врешті-решт, комп'ютера.

Нарешті, якщо служба працює за схемою 24х7, і якщо це добре відома служба (яка може виявитися у кожного популярного додатка - наприклад, у PDF Reader), то це створює велику поверхню для атаки. Зловмисник може скористатися відомостями про те, що певний популярний додаток встановлює службу, що працює в режимі 24х7, і спробувати зламати її для отримання доступу до комп'ютера.

З огляду на все вищесказане, ви можете здивуватися, чому так багато розробників налаштовують свої служби на постійну роботу, якщо у них є інша можливість. Навіть до Windows 7 було доступно кілька варіантів запуску служб:

  • Disabled (Відключено) повністю відключає службу і запобігає її запуск і запуск залежних служб - це означає, що користувач повинен включити службу вручну з панелі керування або командного рядка
  • Manual (Вручну) запускає службу по потребі (у зв'язку з залежностями інших служб) або при виклику служби з програми за допомогою відповідних API, як буде показано нижче
  • Automatic (Автоматично) запускає службу при вході в систему
  • Automatic Delayed (Автоматично (відкладений запуск) - більш новий тип запуску, що з'явився в Windows Vista, за допомогою якого запуск служби відбувається після завершення завантаження і виконання початкових операцій, що прискорює запуск системи

На жаль, багато ISV (включаючи саму Microsoft) продовжують налаштовувати свої служби на автоматичний (Automated) або автоматичний відкладений запуск (Automatic Delayed), оскільки для всіх це є найпростішим рішенням. Служба просто працює 24х7 і завжди доступна, усуваючи будь-яку необхідність перевірки залежностей або того, чи запущена служба.

Поява служб з запуском по триггеру

Останній пункт вказує на розширюваність. Будучи розробником, ви можете налаштувати будь-яку подію ETW як тригера для служби, що дає вам дуже хороший інструмент для управління запуском і зупинкою служб вашої програми.

Так що ж таке тригер?

Тригер складається з:

  • Типу події тригера
  • Підтипу події тригера
  • Дії, яке повинно бути зроблено під час проведення події тригера
  • Одного або більше елементів даних, пов'язаних з тригером (для певних типів подій тригера)
    Підтип і пов'язані з тригером елементи даних разом встановлюють стан для повідомлення служби про подію. Формат елемента даних залежить від типу події тригера; елемент даних може складатися з бінарних, строкових або многостроковие даних.

Робота з Trigger Start Services
На жаль, в інтерфейсі консолі Windows 7 Services MMC немає графічного представлення Trigger Start Services. Однак у вас є дві можливості. Ви можете як і раніше використовувати старий добрий sc.exe (програма командного рядка Service Configuration) або скористатися методом WIN32 ChangeServiceConfig2 для програмної настройки опцій запуску служби, як буде показано в цій статті.

Використання SC.exe для запиту даних тригера служби (Query Service Trigger Information)
Пора повеселитися. Почнемо з отримання відомостей про конфігурацію деяких служб. Загальна форма для використання конфігурації служби виглядає наступним чином:

sc [Command] [service name] .


Де server опціональний, а за замовчуванням ви працюєте з локальним комп'ютером:

  • command - це операція, яку ви хочете виконати, наприклад, запит даних тригера
  • service name - це ім'я служби, з якої ви хочете працювати
  • options - це різні значення (опції), які ви можете виконати для налаштування служби

Почнемо з запиту певної служби про її конфігурації тригера. Для цього нам знадобиться запустити вікно Windows Shell:

[Ist] 1. Відкрийте меню "Пуск".
2. Введіть CMD в поле пошуку.
3. Виберіть cmd.exe.
4. Введіть sc qtriggerinfo w32time і натисніть клавішу введення.
Ось, як це має виглядати:

Як ви можете бачити, ми запросили дані тригера служби W32time, яка налаштована на запуск при підключенні комп'ютера до домену і зупинку при відключенні від домену.

Microsoft в Windows 7 оновила додаток командного рядка sc.exe для підтримки конфігурації і отримання відомостей про підтримувані триггерах. Введіть sc triggerinfo у вікні Windows Shell і натисніть клавішу введення. Результат буде схожий на той, що наведений нижче, і буде містити всі тригери і відомості про те, як налаштувати служби на їх використання.

ОПИС:
Змінює параметри активації служби.
USAGE:
sc <сервер> triggerinfo [ім'я служби] <параметр1> <параметр2>.

Програмна настройка Trigger Start Services за допомогою ChanceServiceConfig2
Більш цікавим з точки зору розробників аспектом є створення служб, що залежать від тригера, і використання коду для конфігурації служби. У Windows 7 ви можете використовувати функцію ChangeServiceConfig2 для настройки даних тригера служби і функцію QueryServiceConfig2 для їх виклику.

Реєстрація тригера служби проводиться викликом ChangeServiceConfig2 використанням SERVICE_CONFIG_TRIGGER_INFO для параметра dwInfoLevel і поданням даних реєстрації тригера в структурі SERVICE_TRIGGER_INFO за допомогою параметра lpInfo. До того ж, можуть бути вказані додаткові пов'язані з тригером дані. Нижче наведено приклад функції установника служби, який створює тригер USB-пристрої для служби під назвою MyService.

define SERVICE_NAME L "MyService"
// set the device guid
static const GUID GUID_USBDevice = 0x53f56307, 0xb6bf, 0x11d0,
0x1e, 0xfb, 0x8b >>;

BOOL _SetServiceToStartOnDeviceTrigger ()
BOOL fResult = FALSE;

SC_HANDLE hScm = OpenSCManager (
NULL, // local machine
NULL, // active database
SC_MANAGER_CONNECT);

if (hScm! = NULL)
SC_HANDLE hService = OpenService (
hScm,
SERVICE_NAME,
SERVICE_ALL_ACCESS);

If (hService! = NULL)

LPCWSTR lpszDeviceString = L "USBSTOR \\ GenDisk";
SERVICE_TRIGGER_SPECIFIC_DATA_ITEM deviceData =;
deviceData.dwDataType = SERVICE_TRIGGER_DATA_TYPE_STRING;
deviceData.cbData =
(Wcslen (lpszDeviceString) +1) * sizeof (WCHAR);
deviceData.pData = (PBYTE) lpszDeviceString;


SERVICE_TRIGGER st;
st.dwTriggerType =
SERVICE_TRIGGER_TYPE_DEVICE_INTERFACE_ARRIVAL;
st.dwAction = SERVICE_TRIGGER_ACTION_SERVICE_START;
st.pTriggerSubtype = (GUID *) GUID_USBDevice;
st.cDataItems = 1;
st.pDataItems = deviceData;


SERVICE_TRIGGER_INFO sti;
sti.cTriggers = 1;
sti.pTriggers = st;
sti.pReserved = 0;

fResult = ChangeServiceConfig2 (
hService,
SERVICE_CONFIG_TRIGGER_INFO,
sti);
>
CloseServiceHandle (hService);
>
CloseServiceHandle (hScm);

if (! fResult)
printf ( "Service trigger registration failed (.) \ n",
GetLastError ());
>
return fResult;
>


Примітка: всі служби контролюються Service Control Manager (SCM), який ми розглянемо в іншій статті.

Ви можете бачити, як в наведеному вище фрагменті коду ми спочатку беремо дескриптор (hScm) до SCM викликом openSCManager. Далі ми викликаємо openService і проходимо дескриптор до SCM - hscm, і ім'я служби - SERVICE_NAME, до якої ми хочемо отримати доступ. Останній параметр, SERVICE_ALL_ACCESS, вказує, що у нас є повний доступ до служб. Вважаючи, що тепер у нас в службі є вірний дескриптор, ми починаємо створювати окрему структуру, якій скористаємося незабаром слід використовувати службу.

SERVICE_TRIGGER_SPECIFIC_DATA_ITEM задає тип події тригера. Він містить дані про подію тригера служби. У нашому випадку, ми задаємо рядок, що описує підключення USB-диска.

Потім ми задаємо структуру SERVICE_TRIGGER, яка представляє події триггеру служби. Зауважте, що саме тут ми задаємо тип тригера (підключення пристрою), дія (запуск служби), і підтип тригера (певний рід USB-дисків). Слідом ми визначаємо конкретний пристрій, яке викликатиме службу. Зауважте, що ви можете задати список пристроїв і їх GUID. Також слід зазначити, що ми не хочемо спрацьовування тригера запуску служби при підключенні будь-якого USB-пристрою, як то миша або камера. Ми хочемо, щоб служба запускалася тільки при появі USB-диска.

Нарешті, ми задаємо структуру SERVICE_TRIGGER_INFO, яка містить дані події тригера служби. Ця структура просто вказує на структуру SERVICE_TRIGGER, яку ми поставили раніше, і кількість тригерів, число яких в даному випадку дорівнює одному.

Тепер ми можемо викликати функцію ChanceServiceConfig2 і пройти дескриптор до служби, яку ми хочемо налаштувати, параметр SERVICE_CONFIG_TRIGGER_INFO, який вказує, що ми хочемо налаштувати тригер служби, і Null.

От і все. Якщо ви все зробили правильно, то служба запуститися при підключенні USB жорсткого диска.

У наступній статті я розгляну, як написати просту реалізацію служби .NET, яку ми налаштуємо на запуск при підключенні диска USB.

Ви також можете потренуватися в роботі з Windows 7 Trigger Start Services за допомогою тренінгу Windows 7 Online, що є частиною Channel 9 Learning Center.

Посилання по темі