(495) 925-0049, ITShop интернет-магазин 229-0436, Учебный Центр 925-0049
  Главная страница Карта сайта Контакты
Поиск
Вход
Регистрация
Рассылки сайта
 
 
 
 
 

Программирование служб Windows 7 с триггерами (ч.1)

Источник: realcoding

Несколько недель назад мы рассмотрели изоляцию Сессии 0 в свете программной совместимости. Поэтому вполне естественно, что мы возвращаемся к обсуждению служб в контексте Windows 7. Но на этот раз мы поговорим о некоторых выгодах оптимизации служб, доступных в Windows 7. Эта статья посвящена новой возможности Windows 7 - Trigger Start Services. Но прежде, чем мы обратимся к API, давайте обрисуем общий фон служб.

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

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

На протяжении многих лет Windows росла и вместе с ней росло число фоновых служб. Будем честны, фоновые службы в Windows ощущаются довольно болезненно - операционная система изначально поставляется с множеством служб. Помимо этого, независимые разработчики ПО (ISV) и их приложения добавляют еще больше служб. Назовем в пример хотя бы службы обновления программного обеспечения. Вместе с тем, некоторые службы критически важны и требуются в процессе загрузки, в то время как необходимость в других возникает позже, когда определенный пользователь выполняет вход в систему, а иные вовсе не нуждаются в запуске, пока не будут вызваны. Несмотря на это, когда вы смотрите на список запущенных в данный момент служб, вы видите множество служб, которым нет необходимости работать по схеме 24х7.
Что плохого в службах, работающих 24 часа в сутки 7 дней в неделю?
Есть несколько проблем, связанных с наличием служб, работающих по схеме 24х7. Во-первых, зачем что-то должно работать (пускай даже и в фоновом режиме), если в его работе нет нужды? Любой запущенный процесс (включая службы) использует драгоценную память и ресурсы ЦП, которые могли бы использоваться для других приложений и служб. Если вы подсчитаете все службы, запущенные в определенный момент, то они служатся в значительный объем памяти, дескрипторов, потоков и использование ЦП. Все эти "растрачиваемые" ресурсы понижают общую производительность компьютера, его отзывчивость и заставляют пользователя думать, что его компьютеры вялые и медлительные. К тому же, поскольку множество работающих служб настроены на автоматический запуск (начинают работать со входом в систему), эти службы влияют на время загрузки компьютера.

Во-вторых, эти растрачиваемые ресурсы непосредственным образом сказываются на потреблении электроэнергии. Чем больше нагрузки мы даем на ЦП, тем больше электроэнергии компьютер потребляет. Это может быть критически важно для ноутбуков и может сократить время работы батареи на несколько часов.

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

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

Учитывая все вышесказанное, вы можете удивиться, почему так много разработчиков настраивают свои службы на постоянную работу, если у них имеется другая возможность. Даже до Windows 7 было доступно несколько вариантов запуска служб:

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

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

Можно привести множество примеров существующих служб, которые могут расходовать куда меньше ресурсов и стать безопаснее, не работая 24х7. Например, подумайте о службе обновлений, которая проверяет наличие новых обновлений для приложения. Если компьютер не подключен к сети и не имеет IP-адреса, зачем работать этой службе? Она ничего не может сделать, так зачем оставлять работающей программу, которая ничего не делает? Подумайте о службе управления политиками, которая используется при изменении групповых политик или при подключении компьютера к домену или отключении от него, но сейчас, когда компьютер подключен к моей домашней сети, служба, опять же, работает впустую.

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

Решение вышеуказанных проблем заключается в выведении службы из "состояния постоянной работы" в другие виды фоновой активности, такие как запланированные задачи или службы, запускаемые триггером. Эта статья посвящена Windows 7 Trigger Start Services. О Windows 7 Scheduled Tasks можно сказать очень много полезного, что и будет сделано в последующих статьях.

Службы, запускаемые по триггеру (англ. trigger-start service), впервые появились в Windows 7. По сути, это обычная служба, которую вы можете настроить на запуск (или остановку) в случае срабатывания триггера, то есть в определенном случае или состоянии, которые вы сами задаете (например, когда становится доступным IP-адрес или когда он исчезает). Ниже приведен список доступных триггеров, с помощью которых вы можете настроить режим запуска вашей службы:

  • Подключение или отключение устройства
  • Вход в домен или выход из него
  • Открытие или закрытия порта брандмауэра
  • Изменение в групповых политиках
  • Доступность первого IP-адреса / исчезновение последнего IP-адреса
  • Настраиваемое событие - Трассировка событий для Windows (ETW)

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

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

Триггер состоит из:

[lst]

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

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

    Использование SC.exe для запроса данных триггера службы (Query Service Trigger Information)
    Пора повеселиться. Начнем с получения сведений о конфигурации некоторых служб. Общая форма для использования конфигурации службы выглядит следующим образом:

    Код:
    sc <server> [command] [service name] <option1> <option2>...

    Где 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>...

    ПАРАМЕТРЫ:
    start/device/UUID/HwId1/... <Запуск службы после получения строки UUID указанного класса интерфейса устройства с одной или несколькими строками кода оборудования или совместимыми строками кода>
    start/custom/UUID/data0/.. <Запуск службы после получения события от строки UUID указанного настраиваемого поставщика трассировки событий Windows с одним или несколькими двоичными элементами данных в формате шестнадцатеричной строки, например,r ABCDABCD, для задания 4 байтов данных>
    stop/custom/UUID/data0/... <Остановка службы после получения события от строки UUID указанного настраиваемого поставщика трассировки событий Windows с одним или несколькими двоичными элементами данных в формате шестнадцатеричной строки, например, ABCDABCD, для задания 4 байтов данных>
    start/strcustom/UUID/data0/.. <Запуск службы после получения события от строки UUID указанного настраиваемого поставщика трассировки событий Windows с одним или несколькими необязательными элементами данных>
    stop/strcustom/UUID/data0/.. <Остановка службы после получения события от строки UUID указанного настраиваемого поставщика трассировки событий Windows с одним или несколькими необязательными элементами данных>
    start/networkon <Запуск службы при первом IP-адресе>
    stop/networkoff <Остановить службу при отсутствии IP-адресов>
    start/domainjoin <Запуск службы при подключении к домену>
    stop/domainleave <Остановка службы при отсоединении от домена>
    start/portopen/параметр <Запуск службы при открытии сетевого порта. Параметр имеет следующую форму: номер_порта;имя_протокола; путь_к_образу;имя_службы>
    stop/portclose/параметр <Остановка службы при закрытии сетевого порта. Параметр имеет следующую форму: номер_порта;имя_протокола; путь_к_образу;имя_службы>
    start/machinepolicy <Запуск службы при изменении групповой политики компьютера или при ее наличии на момент загрузки>
    start/userpolicy <Запуск службы при изменении групповой политики пользователя или при ее наличии на момент загрузки>
    delete <Удаление текущих параметров активации>


    Так всё, что вам нужно для настройки службы на запуск при появлении IP-адреса, - это ввести sc triggerinfo [имя вашей службы] start/networkon , где "имя вашей службы" заменено на имя той службы, которую вы хотите настроить.

    Программная настройка 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,
           {0x94, 0xf2, 0x00, 0xa0, 0xc9,
           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 = {0};
               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 (%d)\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 при помощи Windows 7 Training Kit for Developers или просмотрев видео, посвященные Windows 7, на Channel 9.

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

Ссылки по теме


 Распечатать »
 Правила публикации »
  Написать редактору 
 Рекомендовать » Дата публикации: 09.12.2009 
 

Магазин программного обеспечения   WWW.ITSHOP.RU
Microsoft 365 Business Standard (corporate)
Microsoft Windows Professional 10, Электронный ключ
Microsoft 365 Apps for business (corporate)
Microsoft 365 Business Basic (corporate)
Microsoft Office для дома и учебы 2019 (лицензия ESD)
 
Другие предложения...
 
Курсы обучения   WWW.ITSHOP.RU
 
Другие предложения...
 
Магазин сертификационных экзаменов   WWW.ITSHOP.RU
 
Другие предложения...
 
3D Принтеры | 3D Печать   WWW.ITSHOP.RU
 
Другие предложения...
 
Новости по теме
 
Рассылки Subscribe.ru
Информационные технологии: CASE, RAD, ERP, OLAP
Безопасность компьютерных сетей и защита информации
Новости ITShop.ru - ПО, книги, документация, курсы обучения
Программирование на Microsoft Access
CASE-технологии
Программирование в AutoCAD
Компьютерный дизайн - Все графические редакторы
 
Статьи по теме
 
Новинки каталога Download
 
Исходники
 
Документация
 
 



    
rambler's top100 Rambler's Top100