C служба windows пример

Службы 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) .

Читайте также:  Windows 10 pro lite 2016 rus

В итоге после создания, изменения, переименования и удаления файл лога будет содержать что-то наподобие:

В самом классе службы Service1 в конструкторе устанавливается ряд опций:

В методе OnStart() для запуска объекта Logger вызывется новый поток:

Новый поток нужен, так как текущий поток обрабатывает только команды SCM и должен возвращаться из метода OnStart как можно быстрее.

Когда от менеджера SCM поступает команда на остановку службы, срабатывает метод OnStop, который вызывает метод logger.Stop() . Дополнительная задержка позволит потоку логгера остановиться:

Однако самого класса службы еще недостаточно. Нам необходимо еще создать устанощик службы.

Создание служб Windows с помощью C#

Служба Windows – это специальная служебная программа, которая запускается операционной системой автоматически при загрузке вне зависимости от статуса пользователя или вручную (в зависимости от настроек).

Службы работают в фоновом режиме и, как правило, выполняют различные технологические задачи.

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

Мы не станем вдаваться в подробности работы служб Windows как таковой потому, что она достаточно подробно описана в литературе по работе с Windows.

В этой статье мы рассмотрим пример создания службы Windows с использованием языка программирования C#.

Создание службы

Для того, чтобы создать проект службы необходимо в окне создания нового проекта выбрать пункт «Служба Windows ».

После этого Visual Studio создаст новый проект с «каркасом» службы.

К сожалению, в отличие, например, от Windows Forms или консольного приложения данный «каркас» не самодостаточен. То есть, установить в систему и запустить в работу такую «пустую» службу нельзя. Необходимо дописать рабочий функционал и логику установки в систему.

В качестве примера создадим службу, которая будет каждую секунду записывать в текстовый файл текущее время.

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

Ниже представлен такой класс для нашей службы.

Служба Windows на C#: ещё один пример

Всем доброго времени суток. На связи Алексей Гулынин. В данной статье я бы хотел привести ещё один пример службы Windows на C#. Ранее мы уже писали службу Windows, но это была WCF-служба, т.е. мы ей отправляли запросы и получали ответы. Сейчас же я бы хотел реализовать следующий пример:

Наша служба будет отслеживать количество запусков калькулятора (процесс calc.exe ). Результат будет записываться в текстовый файл. Сразу приведу код:

Метод CheckIDsCalcProcess() , который выполняется раз в 15 секунд, делает следующее:

Он сравнивает содержимое списка oldProcsID со всеми текущими процессами. Если в списке есть id процесса, которого нет во всех процессах, то данный id удаляется из списка.

Далее нам необходимо корректно установить службу. Приведу содержимое двух бат-файлов для установки и удаления службы. После выполнения данных команд необходимо зайти в службы Windows и запустить нашу службу.

Мы видим, что служба успешно запустилась:

Давайте теперь протестируем работу службы. Запустите несколько процессов калькулятора. После этого у нас на диске C создастся файл calc.txt :

Мы видим, что всё работает.

У нашей службы есть один недостаток, который сразу бросается в глаза. Каждый раз при загрузке компьютера, служба будет заново стартовать, при этом переменная count будет равна 0. Чтобы этого избежать значение переменной count можно записывать в текстовый файл или базу данных, и при старте службы переменной count присваивать это значение.

В данной статье мы реализовали ещё один пример службы Windows на C#.

На связи был Алексей Гулынин, оставляйте свои комментарии, увидимся в следующих статьях.

Пишем свой Windows service

Многие из нас сталкиваются с такой задачей, когда нужно запускать своё приложение при запуске компьютера. Конечно можно поместить ярлык в автозагрузку, но как-то это неправильно. Да к тому же если комп перегрузился, а пользователь не залогинелся, то и ваше приложение тоже не запустится.

Самым верным решением в данной ситуации является написание Windows сервиса.

Пример создания сервиса в Studio 2010, .Net C# под катом

Шаг 1. Создание проекта.

Создайте новый проект, выбрав шаблон Windows Service

Переименуйте класс сервиса как вам нужно.

Читайте также:  Sending mails from linux

Получили такой вод код:

namespace ExampleSrv
<
public partial class MyService : ServiceBase
<
public MyService()
<
InitializeComponent();
>

protected override void OnStart( string [] args)
<
>

protected override void OnStop()
<
>
>
>

* This source code was highlighted with Source Code Highlighter .

Это и есть, собственно, сам сервис.
Используйте OnStart и OnStop события для реализации своей поставленной задачи.

Шаг 2. Добавление установщика.

Чтобы ваш сервис заставить работать, его нужно установить.
Чтобы его установить, он должен иметь установщик.

Клик правой кнопкой… Add installer

Теперь у нас есть serviceProcessInstaller и serviceInstaller

В первом можете поставить значение Account в LocalSystem.
Во втором укажите имя сервиса, описание и не забудьте поставить StartTypeAutomatic.

Шаг 3. Логирование.

Для того чтобы вы смогли узнать что делал ваш сервис, когда он стартовал, завершался или что-нибудь еще, вы можете использовать системное логирование.
Делается это очень легко.
Перетаскиваете из Toolbox в свой сервис EventLog.

Примерно так делается логирование:

public partial class MyService : ServiceBase
<
public MyService()
<
InitializeComponent();
>

protected override void OnStart( string [] args)
<
AddLog( «start» );
>

protected override void OnStop()
<
AddLog( «stop» );
>

public void AddLog( string log)
<
try
<
if (!EventLog.SourceExists( «MyExampleService» ))
<
EventLog.CreateEventSource( «MyExampleService» , «MyExampleService» );
>
eventLog1.Source = «MyExampleService» ;
eventLog1.WriteEntry(log);
>
catch <>
>
>

* This source code was highlighted with Source Code Highlighter .

Шаг 4. Установка.

Чтобы установить сервис, нужно вызвать утилиту установки и передать параметром путь к своему сервису.
Для этого я создал install.bat такого вида:

C:\Windows\Microsoft.NET\Framework\v4.0.30319\installutil.exe D:\. \ExampleSrv\bin\Debug\ExampleSrv.exe
pause

Если вы выбрали в serviceProcessInstaller значением поля AccountUser, то при установке вы должны будете ввести логин и пароль учетной записи, под которой будет запускаться сервис. Внимание! Писать домен перед именем пользователя обязательно!

Запускаем батник обязательно с правами администратора и наблюдаем в конце:

The Commit phase completed successfully.
The transacted install has completed.

Это значит что сервис установлен.
Проверяем:

Пару раз делаем запуск и остановку. Смотрим логи:

Видим когда сервис запускался и останавливался.

Создание службы Windows

В данной статье для примера демонстрируется создание службы, представляющей собой сервер цитат. В ответ на каждый запрос клиента сервер цитат должен возвращать случайную цитату из файла. В первой части решения используются три сборки — одна для клиента и две для сервера.

На рисунке ниже показан общий вид решения. Сборка QuoteServer содержит код, реализующий саму функциональность службы. Она отвечает за чтение файла цитат в кэше памяти и отправку ответов на запросы цитат с помощью сервера сокетов.

Сборка QuoteClient представляет собой многофункциональное клиентское приложение WPF. Это приложение отвечает за создание клиентского сокета для взаимодействия с QuoteServer. Третья сборка — QuoteService — представляет собой саму службу и отвечает за запуск и остановку QuoteServer, т.е. за управлением сервером QuoteServer.

Прежде чем создавать служебную часть этой программы, сначала понадобится создать простой сервер сокетов в дополнительной библиотеке классов на C#, которая будет использоваться из процесса службы.

Создание ключевой функциональности для службы

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

В Windows 7 в виде части компонентов может устанавливаться Simple TCP/IP Services. В состав этого компонента входит TCP/IP-сервер «quote of the day» (цитата дня), или qotd. Этот сервер представляет собой простую службу, которая прослушивает порт 17 и отвечает на каждый запрос случайным сообщением, которое берет из файла \system32\drivers\etc\quotes. В нашем примере службы будет создаваться подобный сервер, но только в отличие от quotd, возвращающего строку в кодировке ASCII, этот сервер должен возвращать строку Unicode.

Сначала создадим библиотеку классов по имени QuoteServer и реализуем в ней код для сервера. Ниже по частям рассматривается код класса QuoteServer, который должен содержаться в файле QuoteServer.cs:

Конструктор QuoteServer() перегружен так, чтобы при вызове ему можно было передавать имя файла и номер порта. Конструктор, в котором передается только имя файла, по умолчанию предусматривает использование для сервера порта с номером 7890. В конструкторе по умолчанию имя файла по умолчанию выглядит как quotes.txt:

Читайте также:  Не работает точка восстановления windows 10 ошибка 81000203

Метод ReadQuotes() — это вспомогательный метод, который считывает все цитаты из файла, указанного в конструкторе. Затем все эти цитаты добавляются в коллекцию quotes типа List . Кроме того, создается экземпляр класса Random, который будет использоваться для возврата случайных цитат. Следующий вспомогательный метод — GetRandomQuoteOf TheDay(). Этот метод возвращает случайную цитату из коллекции quotes:

В методе Start() весь файл с цитатами полностью считывается в коллекцию цитат типа List с использованием вспомогательного метода ReadQuaotes(). После этого запускается новый поток, который немедленно вызывает метод Listener().

Здесь используется поток, потому что метод Start() не может блокироваться и ожидать клиента; он должен немедленно возвращать управление вызвавшей его программе (диспетчеру SCM). Диспетчер SCM будет предполагать, что запуск не удался, если этот метод не будет возвращать ему управление в течение 30 секунд. Поток-слушатель конфигурируется как фоновый, чтобы приложение могло завершить свою работу без остановки этого потока. Свойству Name потока присваивается определенное значение для упрощения процесса отладки, поскольку тогда это значение будет появляться в отладчике.

Функция потока ListenerThread() создает экземпляр TcpListener. Метод AcceptSocket() ожидает подключения клиента. Как только клиент подключается, AcceptSocket() возвращает информацию о сокете, который ассоциируется с этим клиентом. Далее вызывается метод GetRandomQuoteOfTheDay() для отправки клиенту выбираемой произвольным образом цитаты с помощью socket.Send():

Прежде чем переходить к построению службы на основе данного сервера, не помешает написать тестовую программу, которая просто создает экземпляр QuoteServer и вызывает его метод Start(). Это позволит протестировать функциональность сервера без необходимости иметь дело с деталями, касающимися конкретно службы. Тестовый сервер должен запускаться вручную, и его код можно легко просматривать в отладчике.

Чтобы получить такую тестовую программу, давайте создадим новое консольное приложение на C# и назовем его TestQuoteServer. Добавим в него ссылку на сборку класса QuoteServer и скопируем файл, содержащий цитаты, в каталог c:\ProCSharp\Services (иначе придется изменить аргумент конструктора, указав в нем место, куда был скопирован этот файл). После вызова конструктора экземпляра QuoteServer в этом приложении должен вызываться его метод Start(). После создания потока этот метод должен немедленно возвращать управление, чтобы консольное приложение продолжало выполняться до тех пор, пока не будет нажата клавиша :

Обратите внимание, что QuoteServer будет работать с портом 4567 локального хоста, на котором запускается данная программа, поэтому именно такие настройки потребуется далее указать в клиенте.

Пример QuoteClient

Клиент в рассматриваемом примере представляет собой простое приложение WPF, в котором пользователь может запрашивать цитаты из сервера. Это приложение использует класс TcpClient для подключения к работающему серверу, принимает возвращаемое сообщение и отображает его в текстовом поле. Его пользовательский интерфейс содержит только два элемента управления — Button и TextBox. У элемента Button есть событие Click, которое назначается методу OnGetQuote, а у ТехВох — свойство x:Name, которое устанавливается в textQuote.

Информация о сервере и портах, необходимая для подключения конфигурируется с помощью параметров приложения. Эти параметры доступны в окне свойств проекта на вкладке Settings (Параметры):

Здесь можно настраивать параметры ServerName (имя сервера) и PortNumber (номер порта), а также определять другие значения, подлежащие использованию по умолчанию. Если установить параметр Scope (область действия) в User (пользователь), то все производимые здесь настройки будут помещены в конфигурационный файл конкретного пользователя. Благодаря этому, для каждого пользователя приложения можно настроить собственные параметры. Вкладка Settings в Visual Studio предусматривает создание класса Settings, с помощью которого можно читать и записывать параметры. В код клиента потребуется добавить следующие директивы using:

Основная функциональность клиента находится в обработчике события щелчка на кнопке Get Quote (Получить цитату):

Теперь, запустив тестовый сервер и это клиентское приложение Windows, можно протестировать функциональность. На рис показан результат успешного выполнения данного приложения:

Далее можно переходить к реализации в сервере функциональности службы. Программа уже работает, а что нужно еще?

Программа-сервер должна запускаться автоматически во время загрузки системы без осуществления в нее входа какого-либо пользователя. Для управления этим поведением должна использоваться программа управления службой.

Оцените статью