- Практическое руководство. Создание службы программным способом How to: Write Services Programmatically
- Создание службы программным способом To write a service programmatically
- Как в Windows 10 создать собственную системную службу
- Чем службы отличаются от программ, добавленных в автозагрузку
- Создаем службу
- Удаление службы
- Службы Windows
- Создание службы для Windows
Практическое руководство. Создание службы программным способом How to: Write Services Programmatically
Если вы решили не использовать шаблон проекта «Служба Windows», для создания собственной службы вам придется настроить наследование и другие элементы инфраструктуры самостоятельно. If you choose not to use the Windows Service project template, you can write your own services by setting up the inheritance and other infrastructure elements yourself. Создавая службу программным способом, вам необходимо выполнить несколько действий, которые в случае с шаблоном выполняются автоматически. When you create a service programmatically, you must perform several steps that the template would otherwise handle for you:
Для класса службы необходимо настроить наследование от класса ServiceBase. You must set up your service class to inherit from the ServiceBase class.
Для проекта службы необходимо создать метод Main , который определяет запускаемые службы и вызывает для них метод Run. You must create a Main method for your service project that defines the services to run and calls the Run method on them.
Необходимо переопределить процедуры OnStart и OnStop и добавить код, который они должны выполнять. You must override the OnStart and OnStop procedures and fill in any code you want them to run.
Создание службы программным способом To write a service programmatically
Создайте пустой проект, а затем создайте ссылку на необходимые пространства имен. Create an empty project and create a reference to the necessary namespaces by following these steps:
В окне Обозреватель решений щелкните правой кнопкой мыши узел Ссылки и выберите пункт Добавить ссылку. In Solution Explorer, right-click the References node and click Add Reference.
На вкладке .NET Framework найдите System.dll и щелкните Выбрать. On the .NET Framework tab, scroll to System.dll and click Select.
Найдите System.ServiceProcess.dll и щелкните Выбрать. Scroll to System.ServiceProcess.dll and click Select.
Нажмите кнопку ОК. Click OK.
Добавьте класс и настройте для него наследование от ServiceBase. Add a class and configure it to inherit from ServiceBase:
Настройте класс службы, добавив следующий код: Add the following code to configure your service class:
Создайте для класса метод Main и с его помощью определите службы, которые будет содержать класс. userService1 — имя класса. Create a Main method for your class, and use it to define the service your class will contain; userService1 is the name of the class:
Переопределите метод OnStart и укажите обработку, которая должна выполняться при запуске службы. Override the OnStart method, and define any processing you want to occur when your service is started.
Переопределите все прочие методы, для которых нужно задать определенную обработку, и напишите код, благодаря которому служба будет понимать, что нужно делать в каждом случае. Override any other methods you want to define custom processing for, and write code to determine the actions the service should take in each case.
Добавить установщики, необходимые для приложения службы. Add the necessary installers for your service application. Дополнительные сведения см. в разделе Практическое руководство. Добавление установщиков в приложение-службу. For more information, see How to: Add Installers to Your Service Application.
Скомпилируйте проект, выбрав в меню Сборка пункт Собрать решение. Build your project by selecting Build Solution from the Build menu.
Не нажимайте клавишу F5 для запуска проекта — таким способом нельзя запустить проект службы. Do not press F5 to run your project — you cannot run a service project in this way.
Создайте проект установки и настраиваемые действия для установки службы. Create a setup project and the custom actions to install your service. Пример см. в разделе Пошаговое руководство. Создание приложения служб Windows в конструкторе компонентов. For an example, see Walkthrough: Creating a Windows Service Application in the Component Designer.
Установите службу. Install the service. Дополнительные сведения см. в разделе Практическое руководство. Установка и удаление служб. For more information, see How to: Install and Uninstall Services.
Как в Windows 10 создать собственную системную службу
Открыв Диспетчер задач и переключившись на вкладку «Подробности», можно обнаружить ряд процессов, которые явно не имеют никакого отношения к запущенным пользователем прикладным программам. Многие из таких процессов принадлежат службам — особым программным модулям, стартующим вместе с Windows, работающим в скрытом режиме и выполняющим подчас очень важную работу. Но тут у многих может возникнуть вопрос.
А разве прикладные программы не могут работать в скрытом режиме и точно так же запускаться вместе с Windows, будучи добавленными в автозагрузку?
Чем службы отличаются от программ, добавленных в автозагрузку
Это хороший вопрос, и на него можно ответить утвердительно, однако понятие «автозагрузка» часто употребляется в широком смысле слова без различия, что именно и как именно загружается. Если вы имеете общие представления о работе процессов Linux, то наверняка знакомы с такой сущностью как демон. Это процесс, но процесс несвязанный с каким-либо конкретным пользователем и работающий как-бы автономно. Службы в Windows очень похожи на этих самых демонов, они тоже независимы от пользователей. Когда вы добавляете в автозагрузку программу, пусть даже не имеющую графического интерфейса, она запускается в рабочем окружении пользователя при входе последнего в свою учетную запись, тогда как службы запускаются еще до ввода пользователем логина и пароля и напрямую с ним не взаимодействуют.
Теперь, когда вы поняли основную разницу между добавленными в автозагрузку приложениями и службами, мы научимся создавать такие службы сами и использовать их для разных целей, например, для мониторинга портов или еще чего-нибудь; главное — это найти программу или скрипт, который будет выполнять необходимое вам действие.
А еще вам понадобиться бесплатный инструмент Non-Sucking Service Manager, который «превратит» обычный процесс в службу. Название программы не очень благозвучное даже для носителя английского языка, но это не так уже и важно. Главное, что она работает. Скачать ее можно с сайта разработчика nssm.cc/download.
Создавать службу (чисто для примера) мы будем из процесса скрипта PowerShell , замеряющего среднее значения загруженности процессора и сохраняющего данные в текстовый лог.
Вот так он выглядит «изнутри».
Сначала проверим, работает ли сам скрипт. Кликаем по нему ПКМ и выбираем «Выполнить с помощью PowerShell».
Если в консоли будет выведен запрос на разрешение выполнения скриптов, вводим Y и нажимаем ввод .
Если скрипт заработал, вы увидите в консоли текст «Транскрибирование запущенно, выходной файл… и его адрес».
В результате в каталоге со скриптом у вас появится каталог «Logs» с файлом отчета в простом текстовом формате.
Создаем службу
Теперь переходим к работе с Non-Sucking Service Manager. Открыв от имени администратора командную строку и перейдя в расположение исполняемого файла утилиты nssm.exe соответствующей разрядности, выполняем команду nssm install logCPUAvg , где logCPUAvg — имя новой службы.
В открывшемся окошке установщика вы увидите три поля:
- Path – в нем указываем путь к обработчику, то есть PowerShell, файл консоли находится в папке C:\Windows\System32\PowerShell .
- Startup directory – папка с исполняемым файлом обработчика, поле заполнится автоматически.
- Arguments – в этом поле прописываем команду -ExecutionPolicy Bypass -NoProfile -File «полный-путь-к-скрипту» .
Аргумент ExecutionPolicy нужен для предоставления скрипту временных прав на запуск. Если в качестве службы вы устанавливаете какую-нибудь утилиту, то поле может быть оставлено как пустым, так и с указанным в нём аргументом данной конкретной утилиты.
Всё готово, жмем «Install service», чтобы установить службу.
Окно установщика содержит и другие вкладки, дополнительные. Например, на вкладке «Details» можно указать описание и отображаемое в оснастке управления службами имя службы, которое будет отличаться от указанного в команде nssm install, а на вкладке «Log on» выбрать учетную запись, от имени которой станет работать служба.
По умолчанию создаваемая служба работает от имени самой системы, как и положено. Открыв оснастку управления службами, вы увидите в списке и свою службу. Она будет иметь тип запуска «Автоматически», но находиться в остановленном состоянии. Запустится она при следующей загрузке, либо вы сами можете ее запустить.
То, что скрипт заработал, станет видно из того, что в месте его расположения появится папка «Logs» , при этом вывод самой консоли будет скрыт. И вот что интересно. Запустив службу, мы вышли из учетной записи в 12.46, а затем вошли в нее в 12.50, но служба продолжала работать даже в наше отсутствие в системе! Это еще раз говорит о том, что системная служба не связана с пользовательским окружением.
Удаление службы
Помимо того, что вы можете остановить службу в оснастке, переведя ее в статус «Отключена», вы властны ее полностью удалить с помощью той же NSSM. Для этого в командной строке выполняем команду nssm remove имя-службы .
И подтверждаем действие нажатием кнопки «Да» в миниатюрном диалоговом окошке.
Ну вот, теперь вы знаете, как создавать собственные службы для утилит и скриптов, которые могут работать независимо от пользователя в скрытом режиме.
Службы Windows
Создание службы для Windows
Одним из важнейших компонентов ОС Windows являются службы. Фактически это отдельные приложения, которые не имеют графического интерфейса и которые выполняют различные задачи в фоновом режиме. Службы могут быть запущены при старте операционной системы, так и в любой другой момент работы пользователя. Распространенным примером служб являются различные веб-серверы, которые в фоновом режиме прослушивают определенный порт на наличие подключений, и если подключения имеются, то взаимодействуют с ними. Это могут быть также различные вспомогательные сервисы обновлений для других установленных программ, которые обращаются к серверу, чтобы узнать, есть ли новая версия приложения. В общем то мы можем открыть панель служб и сами увидеть все установленные и запущенные службы:
Рассмотрим, как создавать свои службы в C#. В качестве реализуемой задачи выберем наблюдение за изменениями в определенной папке в файловой системе. Теперь создадим для ее выполнения службу.
Вначале создадим новый проект, который будет иметь тип Windows Service . Назовем проект FileWatcherService:
После этого Visual Studio генерирует проект, который имеет все необходимое. Хотя в принципе нам необязательно выбирать именно этот тип проекта, можно было бы создать проект библиотеки классов, и затем в нем определить все необходимые классы.
Итак, новый проект выглядит следующим образом:
Здесь также есть файл Program.cs и есть собственно узел службы Service1.cs .
Служба представляет обычное приложение, но она не запускаетс сама по себе. Все вызовы и обращения к ней проходят через менеджер управления службами (Service Control Manager или SCM). Когда служба запускается автоматически при старте системы или вручную, то SCM обращается к методу Main в классе Program:
Метод Main по умолчанию определен таким образом, чтобы запускать сразу несколько служб, которые определены в массиве ServicesToRun. Однако по умолчанию проект содержит только одну службу Service1. Сам запуск производится с помощью метода Run: ServiceBase.Run(ServicesToRun) .
Сама запускаемая служба представлена узлом Service1.cs. Однако на самом деле это не простой файл кода. Если мы откроем этот узел, то увидим в нем файл дизайнера службы Service1.Designer.cs и класс Service1.
Класс Service1 собственно представляет службу. По умолчанию он имеет следующий код:
Класс службы должен наследоваться от базового класса ServiceBase . Этот класс определяет ряд методов, важнейшие из которых метод OnStart() , который запускает действия, выпоняемые службой, и метод OnStop() , останавливающий службу.
После того, как SCM вызовет метод Main и зарегистрирует службу, происходит непосредственный ее вызов через запуск метода OnStart.
Когда в консоли служб или через командную строку мы посылаем команду на остановку службы, то SCM обращается к методу OnStop для ее остановки.
Кроме этих двух методов в классе службы можно переопределить еще несколько методов базового класса ServiceBase:
OnPause : вызывается при приостановке службы
OnContinue : вызывается при возобновлении работы службы после ее приостановки
OnShutdown : вызывается при завершении работы Windows
OnPowerEvent : вызывается при изменении режима электропитания
OnCustomCommand : вызывается при получении службой пользовательской команды от Менеджера Управления Службами (Service Control Manager / SCM)
В конструкторе класса Service1 вызывается метод InitializeComponent() , который определен в файле дизайнера Service1.Designer.cs:
Единственное, что надо в нем отметить, это установка названия службы (свойство ServiceName):
Это то название, которое будет отображаться в консоли служб после установки данной службы. Мы можем его изменить, а можем и оставить как есть.
Теперь изменим код службы следующим образом:
Ключевым классом, который инкапсулирует всю функциональность, является класс Logger. С помощью объекта FileSystemWatcher он будет вести мониторинг изменений в папке D://Temp. В методе Start() устанавливается, что мы будем отслеживать изменения через объект FileSystemWatcher. И вся работа будет идти, пока булевая переменная enabled равна true . А метод Stop() позволит завершить работу класса.
События FileSystemWatcher позволяют отслеживать все изменения в наблюдаемой папке. При этом будет вестись запись изменений в файл templog.txt. Чтобы не было гонки ресурсов за файл templog.txt, в который вносятся записи об изменениях, процедура записи блокируется заглушкой lock(obj) .
В итоге после создания, изменения, переименования и удаления файл лога будет содержать что-то наподобие:
В самом классе службы Service1 в конструкторе устанавливается ряд опций:
В методе OnStart() для запуска объекта Logger вызывется новый поток:
Новый поток нужен, так как текущий поток обрабатывает только команды SCM и должен возвращаться из метода OnStart как можно быстрее.
Когда от менеджера SCM поступает команда на остановку службы, срабатывает метод OnStop, который вызывает метод logger.Stop() . Дополнительная задержка позволит потоку логгера остановиться:
Однако самого класса службы еще недостаточно. Нам необходимо еще создать устанощик службы.