Программирование служб Windows 7 с триггерами (ч.2)
В предыдущей статье
Приложение-пример состоит из 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 для настройки соответствующего триггера
Обо всем этом уже говорилось подробно в предыдущей статье
Вы можете
После компиляции и запуска стандартного приложения (приложения 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, попытайтесь встроить в нее триггеры.
Вы можете узнать больше о Windows 7, обратившись к
Вы также можете
Источник:
Перевод: Sibiryak
По теме
- Федеративный поиск в Windows 7
- Программируем панель задач Windows 7: панель миниатюр
- Использование сенсоров в приложении: реализация в managed-коде (ч.1)
- Использование сенсоров в приложении: реализация в native-коде (ч.1)
- Я тебя чувствую: использование платформы Sensor в Windows 7
- Доступны записи с Windows 7 PDC Boot Camp
- Fishbowl для Facebook с использованием новой панели задач Windows 7
- Программируем для Windows 7 в Visual Studio 2010
- Новая версия Windows API Code Pack
- Программирование служб Windows 7 с триггерами (ч.1)