Для установки службы нам понадобится класс установщика. Для его добавления нажмем правой кнопкой мыши на проект и в контекстном меню выберем Add - > Component.... Затем в окне добавления нового элемента выберем пункт Installer Class:
По умолчанию для файла установщика генерируется название Installer1.cs. Оставим это название.
После добавления узел установщика в окне обозревателя решения (Solution Explorer) будет содержать два файла: сам файл класса Installer1 и файл дизайнера Installer1.Designer.cs. Откроем файл кода. Сейчас он выглядит так:
using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Configuration.Install; using System.Linq; using System.Threading.Tasks; namespace FileWatcherService { [RunInstaller(true)] public partial class Installer1 : System.Configuration.Install.Installer { public Installer1() { InitializeComponent(); } } }
Теперь изменим его следующим образом:
using System.ComponentModel; using System.ServiceProcess; using System.Configuration.Install; namespace FileWatcherService { [RunInstaller(true)] public partial class Installer1 : Installer { ServiceInstaller serviceInstaller; ServiceProcessInstaller processInstaller; public Installer1() { InitializeComponent(); serviceInstaller = new ServiceInstaller(); processInstaller = new ServiceProcessInstaller(); processInstaller.Account = ServiceAccount.LocalSystem; serviceInstaller.StartType = ServiceStartMode.Manual; serviceInstaller.ServiceName = "Service1"; Installers.Add(processInstaller); Installers.Add(serviceInstaller); } } }
Класс установщика унаследован от класса System.Configuration.Install.Installer. Атрибут [RunInstaller(true)] указывает на то, что класс Installer1 должен вызываться при установке сборки, то есть службы.
Он определяет ряд методов: Install()
(установка), Commit()
(завершает транзакцию установки), Rollback()
(восстанавливает состояние компьютера до установки)
и Uninstall()
(удаление). При необходимости мы можем их переопределить. Но в нашем случае мы будем использовать только конструктор.
В конструкторе вызывается метод InitializeComponent()
, который призван выполнять начальную инициализацию. Он определен в
файле дизайнера Installer1.Designer.cs и по сути ничего не делает:
private System.ComponentModel.IContainer components = null; private void InitializeComponent() { components = new System.ComponentModel.Container(); }
Для установки службы нам также понадобится классы ServiceInstaller и ServiceProcessInstaller. Почему именно два класса? ServiceProcessInstaller управляет настройкой значений для всех запускаемых служб внутри одного процесса (как было рассмотрено в прошлой теме, метод Main класса Program может одновременно запускать несколько служб). Класс ServiceInstaller предназначен для настройки значений для каждой из запускаемых служб. То есть если у нас запускается три службы, то для каждой службы создается свой объект ServiceInstaller. Но в нашем случае в прошлой теме мы определили только одну запускаемую службу, поэтому объекты обоих классов у нас будут только в одном экземпляре.
Через свойства оба класса позволяют задать настройки службы. Основные свойства ServiceProcessInstaller:
Username: определяет, под какой именно учетной записью будет запускаться служба
Password: определяет пароль для запуска службы
Account: определяет тип учетной записи. Может принимать одно из значений перечисления ServiceAccount:
LocalSystem: учетная запись предоставляет широкие привилегии на локальном компьютере и соответствует компьютеру в сети
LocalService: учетная запись соответствует пользователю без привилегий на локальном компьютере и предоставляет любому удаленному серверу учетные данные анонимного доступа
NetworkService: учетная запись предоставляет широкие локальные привилегии и также представляет любому удаленному серверу учетные данные компьютера
User: учетная запись определяется конкретным пользователем в сети
HelpText: возвращает справку, содержащую информацию об установке службы
Некоторые важнейшие свойства ServiceInstaller:
StartType: определяет, как должна запускаться служба - автоматически или вручную. Может принимать следующие значения: ServiceStartMode.Automatic (автоматический запуск), ServiceStartMode.Manual (вручную) и ServiceStartMode.Disabled (служба по умолчанию отключена)
DelayedAutoStart: определяет, должна ли служба запускаться не сразу после загрузки операционной системы, а немного позже
DisplayName: устанавливает имя службы, которое будет отображаться в различных утилитах управления службами
ServiceName: имя службы, должно совпадать со значением свойства ServiceName у класса службы
То есть в нашем случае для службы установлен запуск вручную, и ей будут предоставляться широкие привилегии.
В конце оба объекта установщиков надо добавить в коллекцию Installers: Installers.Add()
Итак, у нас готов код службы и код инсталяторов. Теперь скомпилируем проект, и в проекте в папке bin/Debug у нас будет лежать исполняемый файл службы, который будет называться по имени проекта и иметь расширение exe. Например, в моем случае он называется FileWatcherService.exe.
И теперь нам надо установить службу. Для этого нам надо запустить специальную утилиту InstallUtil.exe и передать ей имя файла службы.
Утилиту InstallUtil.exe можно найти по пути C:\Windows\Microsoft.NET\Framework64\v4.0.30319 для 64-битных платформ и в C:\Windows\Microsoft.NET\Framework\v4.0.30319 для 32-битных.
Также можно вынести исполняемый файл службы в какое-нибудь другое место, например, я поместил его в папку D://servces. Тогда установка службы в командной строке будет выглядеть так:
И если мы зайдем после успешной установки в консоль служб, то сможем найти только что установленную службу.
Мы ее можем запустить, и она будет выполнять все те действия, которые мы в ней определили.
Если нам служба больше не нужна, и мы хотим ее удалить, то мы можем воспользоваться той же утилитой, передав ему флаг u:
C:\Windows\Microsoft.NET\Framework64\v4.0.30319>InstallUtil.exe /u D://servces/FileSystemWatcher.exe
И после запуска созданная служба будет мониторить все действия с файлами в папке D://Temp и записывать информацию о действиях в текстовый файл.