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

Автор: Topol Четверг, Май 3rd, 2012 Нет комментариев

Рубрика: Операционные системы

В предыдущей статье о программировании служб Windows 7 с триггерами мы представили Windows 7  Trigger Services в качестве замечательного способа оптимизировать ваши службы для повышения производительности и безопасности. В этой статье мы рассмотрим, как превратить службу, настроенную на автоматический запуск, в службу, запускающуюся по триггеру только после того, как в системе произошло определенное событие. Мы используем WPF-приложение (то есть управляемый код), которое регистрирует и следит за службой (также созданной с использованием .NET). Для связи между миром .NET  и Win32 API, который мы видели в прошлой статье, мы используем слой взаимодействия C++/CLI.

Приложение-пример состоит из 3 частей:

  • Слой взаимодействия C++/CLI, который проводит обычный и простой .NET API в приложение контроллера
  • Приложение контроллера WPF , которое позволяет вам регистрировать и запускать службу
  • Простая служба .NET, которая проверяет наличие запоминающего устройства USB (жесткого диска) и на нем ищет папку под названием «ToCopy» для копирования из нее файлов в локальную папку «C:\FromUSB«.

Нижеследующее изображение иллюстрирует структуру решения.

Давайте начнем с рассмотрения реализации кода службы .NET. Это простая служба Windows, написанная на C#. Цель этой службы заключается в автоматическом копировании изображений с запоминающего устройства USB, подключенного к вашему компьютеру, на ваш локальный жесткий диск — «c:\FromUSB«.

Реализация службы может быть найдена в USBService.cs. Этот класс наследует базовый класс ServiceBase и переопределяет методы OnStart иOnStop. В этом классе имеется метод DoWork, который и выполняет все копирование с диска USB на ваш локальный диск. Метод DoWorkзаписывает данные в файл журнала, за которым мы будем следить.

Наиболее интересная часть реализации службы заключается в методе OnStart. Этот метод вызывается сразу же после запуска службы. Заметьте, что первая строка кода проверяет, настроена ли служба на запуск по триггеру. Если это значение «если» возвращает ложь, то мы создаем новую копию таймера, который производит опрос каждые 5 секунд. До появления Windows 7 это был единственный способ реализации подобной службы, то есть требовалось регулярное опрашивание системы на наличие USB-устройства. Кроме того, данной службе для опроса системы требуется быть запущенной 24х7. Это приводит к крайне неразумному расходованию ресурсов, не позволяет системе переходить в энергосберегательный режим и, наряду с некоторыми другими отрицательными факторами, увеличивает поверхность атаки приложения.

Но с Windows 7 вы можете настроить такую службу при помощи триггера подключения устройства USB. Это означает, что служба не будет работать до тех пор, пока не подключено устройство USB, а точнее универсальное дисковое устройство USB. Мы перейдем к этой части решения уже через секунду, но сейчас, если вы посмотрите на метод OnStart, то заметите, что мы проверяем, настроена ли служба как служба на запуск по триггеру; если это так, мы просто вызываем в другом потоке метод DoWork, как это показано в приведенном ниже фрагменте кода. Всё это должно хорошо работать, поскольку служба НЕ включена и будет запущена только после срабатывания триггера. И, затем, для обработки очереди работы здесь используется пул потоков.

Код:
protected override void OnStart(string[] args)
{
if (ServiceControl.IsServiceTriggerStart(ServiceName))
{
ThreadPool.QueueUserWorkItem(_ => DoWork());
}
else
{
_timer = new Timer(_ => DoWork());
_timer.Change(0, 5000);
}
}

Пространство имен ServiceControl содержит слой взаимодействия C++/CLI. Этот слой использует C++/CLI в качестве связующего элемента между нативным API и приложением WPF. Основной файл ServiceControlInterop.cpp содержит всю функциональность, которая необходима нам и которая используется приложением WPF. Например, используя приложение контроллера, мы можем использовать AddService(…) илиRemoveService(…) для добавления или удаления службы соответственно. Мы также может настроить службу для запуска по триггеру либо при подключении устройства USB, либо при появлении IP-адреса, используя SetServiceTriggerStartOnUSBArrival илиSetServiceTriggerStartOnIPAddressArrival соответственно. Рассмотрение реализации обеих функций показывает, что обе они действует одинаковым образом. Они:

  • Сначала используют OpenSCManager, чтобы поместить дескриптор в Service Control Manager (SCM)
  • Затем используют дескриптор SCM OpenService, чтобы получить настоящий дескриптор службы, которую мы хотим настроить
  • Наконец, они вызывают ChangeServiceconfig2 для настройки соответствующего триггера

Обо всем этом уже говорилось подробно в предыдущей статье Программирование служб Windows 7 с триггерами (ч.1).

Вы можете загрузить образец кода этого приложения. Обратите внимание, что вам потребуется запустить Visual Studio с правами администратора (см. изображение ниже), так как вам потребуется регистрировать, запускать и останавливать службы. Также вам потребуется Windows 7 SDK для компиляции той части решения, которая написана на С++.

После компиляции и запуска стандартного приложения (приложения WPF) вы увидите следующую картину.

Это основное окно приложения контроллера WPF. Отсюда вы можете создавать службы, нажимая на кнопку Create Manual.

Затем откройте окно служб, набрав «Services» в поле поиска меню «Пуск». Вы должны увидеть окно служб. Найдите USBCopyService; она должна выглядеть следующим образом:

Нажмите кнопку Run (Запуск) и затем кнопку Refresh (Обновить) в окне служб или просто нажмите F5. Вы не увидите больших изменений, но статус USBCopyService должен измениться с Manual на Started, как показано ниже:

Повторное обращение к нашему приложению покажет активность службы в файле журнала. Как вы можете видеть на нижеприведенном изображении, служба проявляла активность каждые 5 секунд и опрашивала систему в поисках USB-устройства:

Нажмите кнопку Stop, чтобы остановить службу и затем нажмите Delete Service, чтобы удалить ее. Теперь нажмите кнопку Trigger Start, чтобы зарегистрировать и настроить службу на запуск по триггеру при подключении универсального дискового устройства USB. Если вы проверите окно служб, то увидите, что для службы USBCopyService указано «manual», в то время как на самом деле она настроена для запуска по событию триггера (просто для этого нет графического представления).

Если вы подключите USB-диск с папкой «ToCopy», служба запустится и скопирует файлы в c:\FromUSB. Не самая лучшая реализация, но это всего лишь демонстрация. На изображении, приведенном ниже, в файле журнала имеется всего одна строка, потому что служба была запущена лишь единожды; она выполнила метод DoWork и затем завершила свою работу. Она не работала постоянно и не опрашивала систему каждые 5 секунд и, следовательно, не растрачивала ресурсы и не была подвержена угрозам безопасности.

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

Источник: thevista.ru

Оставить комментарий

Чтобы оставлять комментарии Вы должны быть авторизованы.

Похожие посты