Линк.

advertisement
Знакомство со служебными приложениями Windows
Службы Microsoft Windows (ранее называвшиеся службами Windows NT) позволяют создавать исполняемые приложения, работающие продолжительное время и выполняющиеся в отдельной сессии Windows. Эти службы не содержат элементов пользовательского интерфейса и могут быть автоматически запущены при загрузке компьютера, а также остановлены и запущены повторно. Это дает возможность использовать службы на сервере, а
также на любом другом компьютере, где требуется обеспечить выполнение каких-либо задач так, чтобы не мешать
пользователям, работающим на этом же компьютере. Кроме того, службы могут быть запущены не в контексте безопасности текущего пользователя Windows, а в контексте безопасности другого пользователя или учетной записи
компьютера по умолчанию. Дополнительные сведения о службах и сеансах Windows см. в разделе About Services
документации по платформе SDK, расположенной в библиотеке MSDN.
Примечание. Шаблоны проекта служебного приложения Windows и связанные с ними функциональные
возможности недоступны в стандартном выпуске Visual Basic и Visual C# .NET. Дополнительные сведения см. в
разделе Возможности стандартного выпуска Visual Basic или Возможности стандартного выпуска Visual C#.
Служба может быть создана путем создания приложения, которое устанавливается в качестве службы.
Например, если требуется отслеживать показания счетчика производительности и реагировать на превышение ими
пороговых значений, можно написать служебное приложение Windows, которое будет считывать эти показания,
развернуть приложение и приступить к сбору и анализу данных.
Служба создается как проект Microsoft Visual Studio .NET. В проект помещается код, определяющий команды, которые могут быть посланы службе, и действия, которые должны быть выполнены в ответ на эти команды.
Службе могут быть посланы команды запуска, остановки, приостановки и возобновления выполнения службы, а
также требование выполнить пользовательскую команду.
После создания и построения приложения для его установки необходимо запустить из командной строки
программу InstallUtil.exe и указать ей путь к исполняемому файлу службы, или же использовать средства развертывания Visual Studio. В дальнейшем для настройки, запуска, остановки или приостановки этой службы можно использовать диспетчер управления службами. Часть этих задач может быть также решена с использованием узла
служб в обозревателе серверов или класса ServiceController.
Служебные приложения и остальные типичные приложения
Работа служебных приложений имеет ряд отличий от проектов других типов.

Чтобы проект начал работать, исполняемый файл, созданный после компиляции проекта служебного
приложения, должен быть предварительно установлен на сервер. Служебное приложение невозможно отлаживать
или запускать на выполнение путем нажатия клавиш F5 или F11; нельзя производить непосредственный запуск
службы или пошаговую отладку ее кода. Вместо этого необходимо установить и запустить службу, а затем использовать отладчик для отладки процесса данной службы. Дополнительные сведения см. в разделе Отладка служебных
приложений Windows.

В отличие от проектов других типов, для служебных приложений необходимо создавать компоненты
установки. Компоненты установки устанавливают и регистрируют службу на сервере, а также используют диспетчер управления службами Windows для создания соответствующей записи об этой службе. Дополнительные сведения см. в разделе Добавление установщиков в служебное приложение.

Метод Main служебного приложения должен послать команду запуска службам, входящим в состав
проекта. Метод Run загружает службы в диспетчер управления службами соответствующего сервера. При использовании шаблона проекта служебного приложения данный метод создается автоматически. Необходимо помнить,
что загрузка службы — не то же самое, что ее запуск. Дополнительные сведения см. далее в разделе «Время жизни
службы».

Служебное приложение Windows выполняется на отдельной рабочей станции, не совпадающей со
станцией пользователя системы. Рабочая станция — это объект, содержащий буфер обмена, набор глобальных атомов и группу объектов рабочего стола. Поскольку станция службы Windows не является интерактивной, то диалоговые окна, вызываемые из служебного приложения Windows, не будут отображаться и могут привести к зависанию программы. Аналогичным образом, сообщения об ошибках должны записываться в журнал событий Windows,
а не выводиться на экран.
Классы служб Windows, поддерживаемые .NET Framework, не поддерживают взаимодействие с интерактивными станциями, то есть, станциями текущего пользователя. В NET Framework отсутствуют также классы,
представляющие станции и рабочие столы. При необходимости организовать взаимодействие службы Windows с
другими станциями следует использовать неуправляемый API Windows. Дополнительную информацию см. в разделе Рабочие станции и Рабочие столы документации по платформе SDK.
Взаимодействие службы Windows с пользователем или другими станциями должно быть тщательно спроектировано с целью учета таких ситуаций, как наличие пользователя, не вошедшего в систему, или пользователя,
имеющего непредвиденный набор объектов рабочего стола В некоторых случаях более целесообразным будет создание приложения Windows, выполняющегося под управлением пользователя.

Служебные приложения Windows выполняются в собственном контексте безопасности и запускаются до того как пользователь войдет в систему на компьютере, на котором они установлены. Необходимо с осторожностью подходить к вопросу выбора учетной записи, от имени которой будет запускаться служба; службы, запущенные от имени системной учетной записи, имеют больше прав и привилегий, чем службы, запущенные от имени
учетной записи пользователя.
Время жизни службы
В процессе функционирования служба проходит несколько состояний. Сначала служба устанавливается на
компьютер, на котором она будет работать. При этом для проекта службы запускаются установщики, а сама служба
устанавливается в диспетчер управлениями службами этого компьютера. Диспетчер управления службами является
основным средством управления службами, предоставляемым Windows.
После установки службы ее необходимо запустить. После запуска служба может выполнять свои задачи.
Служба может быть запущена с помощью диспетчера управления службами, с помощью обозревателя серверов или
же с помощью вызова метода ServiceController.Start. Метод Start передает управление методу OnStart вызываемого
приложения и выполняет содержащийся в нем код.
В запущенном состоянии служба может находиться неограниченное время, пока она не будет остановлена
или приостановлена, или же пока компьютер не завершит работу. Существуют три основных состояния службы:
запущена, остановлена или приостановлена. Кроме того, служба может находиться в состоянии ожидания выполнения команды: ContinuePending, PausePending, StartPending или StopPending. Это говорит о том, что отправленная
службе команда (например, команда приостановки или запуска службы) находится в процессе выполнения. Для
определения состояния службы можно проверить свойство ServiceController.Status или с помощью метода
ServiceController.WaitForStatus попытаться выполнить какие-либо действия при наступлении одного из этих состояний.
Служба может быть запущена с помощью диспетчера управления службами, с помощью обозревателя серверов или же путем вызова соответствующих методов в коде приложения. Каждое из этих действий вызывает соответствующую процедуру службы (OnStop, OnPause или OnContinue), в которой можно задать дополнительные действия, с тем чтобы они были выполнены при изменении состояния службы.
Типы служб
Используя , в Visual Studio .NET , можно создать два типа служб. Службы, являющиеся единственной
службой в процессе, принадлежат к типу Win32OwnProcess. Службы, разделяющие процесс с другими службами,
принадлежат к типу Win32ShareProcess. Получить тип службы можно путем считывания значения свойства
ServiceController.ServiceType.
При попытке считать значение этого свойства для служб, которые были созданы не в , или в Visual
Studio .NET, могут быть получены и другие значения. Дополнительные сведения см. в разделе Перечисление
ServiceType.
Службы и компонент ServiceController
Компонент ServiceController используется для подключения к установленной службе и изменения ее состояния. С помощью компонента ServiceController можно запустить и остановить службу, приостановить ее или
продолжить выполнение, а также отправить службе пользовательскую команду. Однако при создании служебного
приложения нет необходимости в использовании компонента ServiceController. Фактически в большинстве случаев компонент ServiceController должен находиться не в самом служебном приложении Windows, а в отдельном
приложении.
Дополнительные сведения о компоненте ServiceController см. в разделе Наблюдение за службами
Windows.
Развертывание и установка служб
Visual Studio .NET предоставляет разработчику компоненты установки, которые используются для установки ресурсов, связанных с необходимым служебным приложением. Компоненты установки регистрируют службу на компьютере, на котором она устанавливается, а также сообщают о ее существовании диспетчеру управления
службами.
После добавления установщиков необходимо создать проект установки, который будет устанавливать откомпилированные файлы проекта и запускать установщики, необходимые для установки службы. Для завершения
создания проекта установки необходимо добавить к нему выходные файлы проекта службы и пользовательские
действия, которые выполняют установку службы. Дополнительные сведения о проектах установки см. в разделе
Проекты установки. Дополнительные сведения о пользовательских действиях см. в разделе Пример. Создание
пользовательского действия.
Требования

Службы должны создаваться с использованием проекта служебного приложения Windows или другого типа проекта, поддерживаемого .NET, который наследуется от класса ServiceBase и при построении которого
будет создан EXE-файл.

В состав проектов, содержащих службы Windows, должны входить компоненты установки для самого проекта и его служб. Для этого можно использовать настройки, задаваемые в окне свойств. Дополнительные
сведения см. в разделе Добавление установщиков в служебное приложение.
Пример. Создание служебного приложения Windows в конструкторе компонентов
Примечание. Шаблон служб Windows и связанные с ней функции не доступны в стандартном выпуске Visual Basic
и Visual C# .NET. Дополнительные сведения см. в разделе Возможности стандартного выпуска Visual Basic или Возможности стандартного выпуска Visual C#.
Представленные в данном разделе процедуры подробно описывают процесс создания простого служебного приложения Windows, записывающего сообщения в журнал событий. Для создания службы необходимо выполнить следующие основные шаги:
2

Создать проект с помощью шаблона служебного приложения Windows. Этот шаблон создает производный от
ServiceBase класс и формирует основную часть кода службы — например, код, необходимый для ее запуска.

Написать код процедур OnStart и OnStop и переопределить любые другие требуемые методы.

Добавить установщики, необходимые для служебного приложения. По умолчанию при щелчке ссылки Добавить установщик в приложение добавляется класс, содержащий два или более установщика: один установщик
предназначен для установки процесса, а другой — для каждой связанной c проектом службы.

Собрать проект.

Создать проект установки, предназначенный для установки службы, и выполнить его установку.

Перейти в диспетчер управления службами Windows 2000 и запустить службу.
В начале необходимо создать проект и установить значения, необходимые для правильной работы службы.
Чтобы создать и настроить службу
1.
В меню Файл выберите команду Создать и затем щелкните Проект.
Будет отображено диалоговое окно Создать проект.
2.
Из списка шаблонов проектов Visual Basic или Visual C# выберите проект Служба Windows и присвойте ему
имя MyNewService.
Примечание. Шаблон проекта автоматически добавит класс компонента с именем Service1, наследуемый от
System.ServiceProcess.ServiceBase.
3.
В конструкторе выберите Service1. В окне «Свойства» укажите значение MyNewService свойства
ServiceName.
4.
Установите значение true свойства AutoLog.
5.
В меню Вид выберите команду Код для открытия редактора кода. Измените метод Main, чтобы создать экземпляр MyNewService. При переименовании службы в п. 3 имя класса в методе Main не было изменено. Для
доступа к методу Main в Visual Basic откройте область Код, автоматически созданный конструктором компонентов.
6.
// C#
7.
static void Main()
8.
{
9.
System.ServiceProcess.ServiceBase[] ServicesToRun;
10.
// Change the following line to match.
11.
ServicesToRun = new System.ServiceProcess.ServiceBase[]
12.
{ new M y N e w S e r v i c e () };
13.
System.ServiceProcess.ServiceBase.Run(ServicesToRun);
}
В следующем разделе к службе Windows будет добавлен пользовательский журнал событий. Журналы событий не
связаны каким-либо образом со службами Windows. Компонент EventLog используется здесь как пример типа компонентов, который можно добавить в службу Windows. Дополнительные сведения о пользовательских журналах событий см. в разделе Создание и удаление пользовательских журналов событий.
Чтобы добавить к службе работу с журналом событий
1.
В обозревателе решений щелкните правой кнопкой Service1.vb или Service1.cs и выберите Конструктор
представлений.
2.
Перетащите компонент EventLog из вкладки Компоненты области элементов в конструктор.
3.
В обозревателе решений щелкните правой кнопкой Service1.vb или Service1.cs и выберите Просмотреть
код.
4.
Измените конструктор, чтобы определить пользовательский журнала событий. Для доступа к конструктору в
Visual Basic откройте область Код, автоматически созданный конструктором компонентов.
5.
// C#
6.
public MyNewService()
7.
{
8.
InitializeComponent();
9.
if (!System.Diagnostics.EventLog.SourceExists("MySource"))
10.
{
11.
System.Diagnostics.EventLog.CreateEventSource(
12.
"MySource","MyNewLog");
13.
}
14.
eventLog1.Source = "MySource";
15.
eventLog1.Log = "MyNewLog";
}
Чтобы определить действия при старте службы

В редакторе кода откройте метод OnStart, который был автоматически переопределен при создании проекта,
и напишите код, задающий действия при запуске службы:

// C#

protected override void OnStart(string[] args)
3


{
eventLog1.WriteEntry("In OnStart");
}
Примечание. Стоит отметить, что служебное приложение предназначено для длительного выполнения.
Оно обычно опрашивает или отслеживает что-либо в системе. Отслеживание задается в методе OnStart.
Тем не менее, метод OnStart не выполняет фактического отслеживания. Метод OnStart должен передавать
управление в операционную систему сразу после начала работы службы. Он не должен содержать бесконечный цикл или блокироваться. Для задания простого механизма опроса можно воспользоваться компонентом System.Timers.Timer. В методе OnStart можно задать параметры компонента и затем установить
значение true свойства Timer.Enabled. Таймер будет выполнять в коде периодическую генерацию событий,
во время которых служба может производить отслеживание.
Чтобы определить действия при остановке службы

В редакторе кода откройте метод OnStop, который был автоматически переопределен при создании проекта,
и напишите код, задающий действия при остановке службы:

// C#

protected override void OnStop()

{

eventLog1.WriteEntry("In onStop.");
}
Кроме того, для указания дальнейшей обработки можно определить методы компонента OnPause, OnContinue и
OnShutdown.
Чтобы определить иные действия для службы

Переопределите соответствующий метод обработки, указав необходимые действия.
В следующем коде показан результат переопределения метода OnContinue:
// C#
protected override void OnContinue()
{
eventLog1.WriteEntry("In OnContinue.");
}
При установке службы Windows нужно выполнить некоторые пользовательские действия, что может быть сделано с
помощью класса Installer. С помощью Visual Studio для службы Windows можно специально создать такие установщики и добавить их в проект.
Чтобы создать установщики для службы
1.
Для Service1 возвратитесь в режим разработки.
2.
Щелкните фон конструктора для выбора самой службы, а не какого-либо ее элемента.
3.
В окне «Свойства» щелкните ссылку Добавить установщик, располагающуюся в серой области ниже списка
свойств.
По умолчанию в проект добавляется класс компонента, содержащий два установщика. Компоненту присваивается имя ProjectInstaller, а содержащиеся в нем установщики предназначаются для установки службы и связанного со службой процесса.
4.
Для ProjectInstaller выберите режим разработки и щелкните по ServiceInstaller1.
5.
В окне «Свойства» установите значение MyNewService свойства ServiceName.
6.
Установите значение Automatic свойства StartType.
7.
В конструкторе выберите ServiceProcessInstaller1 (для проекта на Visual Basic) или serviceProcessInstaller1
(для проекта на Visual C#). Установите значение LocalService свойства Account. Это приведет к установке и
выполнению службы с использованием учетной записи локальной службы. Дополнительные сведения см. в разделе Свойство ServiceProcessInstaller.Account.
Примечание о безопасности Учетная запись LocalService действует как непривилегированный пользователь
локального компьютера и предоставляет анонимные учетные данные любому удаленному серверу. Другие
учетные записи следует использовать с осторожностью, поскольку они имеют более полные права доступа и
увеличивают риск атак, исходящих он злонамеренного кода.
Чтобы построить проект службы
1.
В обозревателе решений щелкните проект правой кнопкой мыши и выберите команду Свойства контекстного меню. Будет отображено диалоговое окно Страницы свойств проекта.
2.
В левой области выберите вкладку Общие папки Обычные свойства.
3.
Из списка Начальный объект выберите MyNewService (для проекта на Visual Basic) или
MyNewService.MyNewService (для проектов на Visual C#). Нажмите OK.
4.
Для построения проекта нажмите CTRL+SHIFT+B.
После того, как проект построен, он может быть развернут. Проект установки установит скомпилированные файлы
проекта и выполнит установщики, необходимые для запуска службы Windows. Для создания полного проекта установки в проект установки необходимо сначала добавить выходной файл проекта (MyNewService.exe), а затем пользовательское действие, необходимое для его установки. Дополнительные сведения о проектах установки см. в разделе
4
Проекты установки. Дополнительные сведения о пользовательских действиях см. в разделе Пример. Создание пользовательского действия.
Чтобы создать для службы проект установки
1.
В меню Файл укажите Добавить проект и затем выберите Новый проект.
2.
В области Типы проектов выберите папку Проект установки и развертывания.
3.
В области Шаблоны выберите Установочный проект. Назовите проект MyServiceSetup.
Проект установки добавлен в решение.
Следующее, что нужно сделать — это добавить в установку выходной файл проекта службы Windows
(MyNewService.exe).
Чтобы добавить в проект установки MyNewService.exe
1.
В обозревателе решений щелкните правой кнопкой по MyServiceSetup, укажите Добавить и выберите Выходной элемент проекта.
Будет отображено диалоговое окно Добавление выходной группы проекта.
2.
В окне Проект будет выбрано MyNewService.
3.
Выберите из списка Основной вывод и нажмите ОK.
В проект установки будет добавлен элемент, соответствующий основному выходному файлу проекта
MyNewService. Теперь следует добавить пользовательское действие, необходимое для установки файла
MyNewService.exe.
Чтобы добавить в проект установки пользовательское действие
1.
В обозревателе решений щелкните правой кнопкой мыши проект установки, укажите Вид и выберите Пользовательские действия.
Будет отображен редактор пользовательских действий.
2.
В редакторе пользовательских действий щелкните правой кнопкой узел Пользовательские действия и
выберите Добавить пользовательское действие.
Будет отображено диалоговое окно Выбор элемента в проекте.
3.
Для открытия в списке дважды щелкните Папка приложения, выберите Основной вывод для
MyNewService (Активно) и нажмите OK.
Во все четыре узла пользовательских действий (Установка, Сохранение, Откат и Удаление) будет добавлен
основной выходной файл проекта.
4.
В обозревателе решений щелкните правой кнопкой MyServiceSetup и выберите Построить.
Чтобы установить службу Windows

Для установки MyEventLog.exe в обозревателе решений щелкните правой кнопкой мыши проект установки и
выберите Установить.
Чтобы запустить и остановить службу
1.
Откройте диспетчер управления службами одним из следующих способов:

В Windows 2000 Professional щелкните правой кнопкой на рабочем столе Мой компьютер и выберите Управление. В окне Управление компьютером откройте узел Службы и приложения.
–или–

В Windows 2000 Server щелкните Пуск, выберите Программы, щелкните Администрирование и
Службы.
Примечание. В Windows NT версии 4.0 диалоговое окно можно открыть на панели управления.
2.
После этого служба MyNewService будет отображена в разделе Службы окна.
3.
Выберите службу из списка, щелкните ее правой кнопкой мыши и щелкните Пуск.
4.
Щелкните службу правой кнопкой мыши и выберите команду Стоп.
Чтобы проверить формирование журнала событий службы
1.
Откройте обозреватель серверов и выберите узел Журналы событий. Дополнительные сведения см. в разделе Работа с журналами событий в обозревателе серверов
Примечание. Узел Серверы обозревателя серверов недоступен в стандартном выпуске Visual Basic и Visual
C# .NET. Дополнительные сведения см. в разделе Возможности стандартного выпуска Visual Basic или Возможности стандартного выпуска Visual C#.
2.
Найдите список для MyNewLog и откройте его. Будут отображены сведения о выполненных службой действиях.
Чтобы удалить службу

В меню Пуск выберите Панель управления, щелкните Установка/удаление программ, найдите нужную
службу и щелкните Удалить.

Кроме того, удалить программу можно, щелкнув правой кнопкой значок программы для файла .msi и выбрав
Удалить.
Примечание. Если служба была установлена в Windows 2000, то перед ее удалением необходимо перезагрузить систему. В Windows 2000 службы удаляются не полностью до перезагрузки системы.
Последующие шаги
Кроме того, можно изучить возможности компонента ServiceController, позволяющего отправлять команды в установленную службу. Дополнительные сведения об использовании компонента ServiceController см. в разделе Наблюдение за службами Windows.
5
Для создания журнала событий при установке приложения можно воспользоваться установщиком, а не создавать
журнал после запуска приложения. Кроме того, в этом случае журнал событий будет удален установщиком при удалении приложения. Дополнительные сведения см. в разделе Пример: Установка компонента журнала событий.
Программная архитектура служебного приложения
Основой служебных приложений Windows является класс, наследуемый от класса System.ServiceProcess.ServiceBase.
Чтобы определить поведение службы, необходимо переопределить методы этого класса, задав для них требуемые
функциональные возможности.
Основными классами, используемыми при создании службы, являются следующие.

System.ServiceProcess.ServiceBase — при написании кода, определяющего поведение службы на основе этого
унаследованного класса, необходимо при создании службы переопределить методы класса ServiceBase.

System.ServiceProcess.ServiceProcessInstaller и System.ServiceProcess.ServiceInstaller — используются для
установки и удаления службы.
Кроме того, для управления службой можно использовать класс ServiceController. Этот класс не участвует в создании
службы, однако с его помощью можно осуществлять запуск и остановку службы, передачу ей команд и возврат последовательности перечислений.
Определение поведения службы
Для задания действий, выполняемых при изменении состояния службы в диспетчере управления службами, необходимо в классе службы переопределить базовые функции класса, отвечающие за эти действия. Для настройки поведения службы можно переопределить описанные ниже методы класса ServiceBase.
Метод
Переопределяется с целью...
OnStart
Указать действия, которые должны быть выполнены при запуске службы. В этой процедуре должен содержаться код, выполняющий требуемые действия.
OnPause
Указать действия, которые должны быть выполнены при приостановке службы.
OnStop
Указать действия, которые должны быть выполнены при остановке службы.
OnContinue
Указать действия, которые должны быть выполнены при возобновлении работы службы после приостановки.
OnShutDown
Указать действия, которые должны быть выполнены непосредственно перед завершением работы системы, если служба в это время запущена.
OnCustomCommand
Указать действия, которые должны быть выполнены службой при получении пользовательской команды. Дополнительные сведения о пользовательских командах см. в библиотеке MSDN.
OnPowerEvent
Определить действия службы при получении события управления питанием (такого как
сигнал низкого уровня зарядки аккумуляторов или активации режима приостановки).
Примечание. Эти методы представляют состояния, которые проходит служба в процессе жизни; служба переходит
из одного состояния в другое. Например, служба не будет отвечать на команду OnContinue, если предварительно не
был вызван метод OnStart.
Ниже представлены еще несколько полезных свойств и методов. В их число входят:

Метод Run класса ServiceBase. Это основная точка входа в службу. При создании службы с использованием
шаблона служебного приложения код, запускающий службу, помещается в приложение в процедуру Sub Main.
Этот код может выглядеть следующим образом.

// C#

System.ServiceProcess.ServiceBase[] ServicesToRun;

ServicesToRun = new System.ServiceProcess.ServiceBase[]

{ new Service1() };
System.ServiceProcess.ServiceBase.Run(ServicesToRun);
Примечание. Эти два примера используют массив типа ServiceBase, в который могут быть добавлены все
службы, содержащиеся в приложении. В дальнейшем эти службы могут быть запущены одновременно. При
создании единичной службы можно не использовать массив, а объявить новый объект, наследуемый от
ServiceBase и запустить его. Пример см. в разделе Создание служб программным путем.

Серии свойств в классе ServiceBase. Эти серии определяют, какие методы могут вызываться службой.
Например, если для свойства CanStop установлено значение true, то служба может вызывать метод OnStop. Если для свойства CanPauseandContinue установлено значение true, то могут быть вызваны методы OnPause и
OnContinue. При установке для какого-либо из этих свойств значения true необходимо переопределить соответствующий метод и написать процедуру обработки.
Примечание. Чтобы служба была работоспособна, методы OnStart и OnStop должны быть переопределены.
6
Для взаимодействия с существующей службой и управления ее поведением можно использовать компонент
ServiceController. Дополнительные сведения об использовании компонента ServiceController см. в разделе Наблюдение за службами Windows.
Создание служб Windows
При создании службы можно воспользоваться шаблоном проекта Visual Studio .NET с именем «Служба Windows».
Этот шаблон выполнит большую часть работы автоматически, используя ссылки на соответствующие классы и пространства имен, устанавливая для служб наследование от базового класса и переопределяя несколько наиболее вероятных методов.
Примечание. Шаблон службы Windows не доступен в стандартном выпуске Visual Basic и Visual C# .NET. Дополнительные сведения см. в разделе Возможности стандартного выпуска Visual Basic или Возможности стандартного
выпуска Visual C#.
Для создания функциональной службы необходимо выполнить следующий минимум действий:

Задать свойство ServiceName.

Создать установщики, необходимые для служебного приложения.

Для настройки поведения службы переопределить и написать код методов OnStart и OnStop.
Следующим (после добавления в приложение установщиков) шагом является создание проекта установки, который
установит откомпилированные файлы проекта и выполнит установщики, необходимые для установки службы. Для
создания полного проекта установки в него необходимо сначала добавить выходной файл проекта служебного приложения, а затем требуемое для установки службы пользовательское действие. Дополнительные сведения о проектах
установки см. в разделе Проекты установки. Дополнительные сведения о пользовательских действиях см. в разделе
Пример. Создание пользовательского действия.
Чтобы создать служебное приложение Windows
1.
Создайте проект службы Windows.
Примечание. Указания о способах создания службы без помощи шаблона см. в разделе Создание служб программным путем.
2.
В окне Свойства для службы установите свойство ServiceName.
Примечание. Значение свойства ServiceName должно всегда соответствовать имени, заданному в классах
установщиков. При изменении этого свойства необходимо также изменить и свойство ServiceName классов
установщика.
3.
Установите любое из следующих свойств для определения способа работы службы.
5.
6.
7.
8.
Свойство
Параметр
CanStop
Для указания, что служба может принимать запросы на прекращение
работы, установите значение true; для предотвращения остановки службы — false.
CanShutDown
Установите значение true для указания того, что служба может принимать уведомления о завершении работы компьютера, на котором она используется; в этом случае имеется возможность вызова процедуры
OnShutDown.
CanPauseAndContinue
Для указания, что служба может принимать запросы на временную остановку или продолжение работы, установите значение true; для предотвращения временной остановки или продолжения работы службы —
false.
CanHandlePowerEvent
Для указания того, что служба может обрабатывать уведомления об изменении состояния питания компьютера, установите значение true, для
предотвращения получения уведомлений о таких изменениях — false.
AutoLog
Для записи информационных данных в журнал событий приложения при
выполнении службой действия установите значение true; для запрещения этого — false. Дополнительные сведения см. в разделе Запись сведений о службах в журнал.
Примечание. По умолчанию свойство AutoLog имеет значение true.
4. Примечание. Если свойства CanStop или CanPauseAndContinue имеют значение false, то команды меню
диспетчера управления службами, соответствующие прекращению, остановке или продолжению работы
службы, запрещаются.
Откройте редактор кода и напишите нужный код обработки процедур OnStart и OnStop.
Переопределите любые методы, которым нужно придать дополнительную функциональность.
Создайте необходимые для служебного приложения установщики. Дополнительные сведения см. в разделе
Добавление установщиков в служебное приложение.
Постройте проект, выбрав команду Построить решение в меню Построение.
7
Примечание. Не следует нажимать кнопку F5 для запуска проекта — запуск проекта службы указанным образом невозможен.
9.
Установите службу. Дополнительные сведения см. в разделе Установка и удаление служб.
Создание служб программным путем
Если не использовать шаблон проекта служебного приложения Windows, то для создания службы необходимо самостоятельно настроить наследование и другие элементы инфраструктуры. При создании службы программными средствами необходимо выполнять ряд действий, которые в шаблоне выполняются автоматически.

Необходимо определить, что класс службы унаследован от класса System.ServiceProcess.ServiceBase.

Для проекта службы необходимо создать метод Main, определяющий службы, которые должны запускаться,
и вызывающий метод Run для этих служб.

Необходимо переопределить процедуры OnStart и OnStop и поместить в них код, который они должны выполнять.
Примечание. Пустой шаблон и шаблон служебного приложения Windows недоступны в стандартном выпуске
Visual Basic .NET; шаблон служебного приложения Windows недоступен в стандартной поставке Visual
C# .NET. Дополнительные сведения см. в разделе Возможности стандартного выпуска Visual Basic или Возможности стандартного выпуска Visual C#.
Чтобы создать службу программными средствами.
1.
Создайте пустой проект и ссылку на необходимые пространства имен. Для этого выполните следующие действия.
a.
В обозревателе решений щелкните правой кнопкой мыши узел Ссылки и выберите команду Добавить ссылку.
b.
На вкладке .NET Framework выберите System.dll и нажмите кнопку Выбрать.
c.
Выберите System.ServiceProcess.dll и нажмите кнопку Выбрать.
d.
Нажмите кнопку OK.
2.
Добавьте класс, настроив его так, чтобы он наследовал от класса System.ServiceProcess.ServiceBase:
3.
// C#
4.
public class UserService1 : System.ServiceProcess.ServiceBase
5.
{
}
6.
Чтобы настроить класс службы, добавьте следующий код.
7.
// C#
8.
public UserService1()
9.
{
10.
this.ServiceName = "MyService2";
11.
this.CanStop = true;
12.
this.CanPauseAndContinue = true;
13.
this.AutoLog = true;
}
14.
Создайте для класса процедуру Sub Main и с ее помощью определите службу, которую будет содержать
класс.
15.
// C#
16.
public static void Main()
17.
{
18.
System.ServiceProcess.ServiceBase.Run(new UserService1());
}
где userService1 — имя класса.
19.
Переопределите метод OnStart и поместите в него код для выполнения действий, необходимых при запуске
службы.
20.
// C#
21.
protected override void OnStart(string[] args)
22.
{
23.
// Insert code here to define processing.
}
24.
При необходимости переопределите другие методы и поместите в них код, определяющий действия службы
в каждом конкретном случае.
25.
Добавьте в служебное приложение необходимые установщики. Дополнительные сведения см. в разделе Добавление установщиков в служебное приложение.
26.
Выполните построение проекта. Для этого выберите в меню Построение команду Построить решение.
Примечание. Проект службы нельзя запустить нажатием клавиши F5.
27.
Создайте проект установки и задайте действия, необходимые для установки службы. Пример. Создание служебного приложения Windows в конструкторе компонентов.
28.
Установите службу. Дополнительные сведения см. в разделе Установка и удаление служб.
Добавление установщиков в служебное приложение
8
В состав Visual Studio .NET входят компоненты установки, которые могут установить ресурсы, связанные со служебными приложениями. Компоненты установки регистрируются как отдельная служба в системе, в которой они устанавливаются; после чего их присутствие распознается диспетчером управления службами. При работе со служебным
приложением для автоматического добавления в проект соответствующих установщиков можно воспользоваться
ссылкой в окне «Свойства». Дополнительные сведения о компонентах установки и способах их работы см. в разделе
Знакомство с компонентами установки.
Примечание. Значения свойств службы копируются из класса службы в класс установщика. При обновлении значений свойств в классе службы они не обновляются автоматически в классе установщика.
При добавлении установщика в проект в нем создается новый класс (с именем ProjectInstaller по умолчанию) и
внутри класса создаются экземпляры соответствующих компонентов установки. Этот класс действует как центральное звено всех нужных для приложения компонентов установки. Например, если щелкнуть ссылку «Добавить установщик» и добавить в приложение вторую службу, то второй класс установщика создаваться не будет; вместо этого в
существующий класс будет добавлен дополнительный компонент установки, необходимый для второй службы.
Для правильной установки служб не требуется создания какого-либо особого кода внутри установщиков. Тем не менее, иногда бывает нужно добавить в процесс установки дополнительные функции. Для этого может потребоваться
изменение содержимого установщиков. Дополнительные сведения см. в разделе Настройка компонентов установки.
После добавления в приложение установщиков следующим шагом является создание проекта установки, который
установит откомпилированные файлы проекта и выполнит действия, необходимые для установки службы. Для создания полного проекта установки в него необходимо сначала добавить выходной файл проекта служебного приложения, а затем требуемое для установки службы пользовательское действие. Дополнительные сведения о проектах установки см. в разделе Проекты установки. Дополнительные сведения о пользовательских действиях см. в разделе Пример. Создание пользовательского действия.
Чтобы добавить установщики в служебное приложение
1.
В обозревателе решений откройте режим разработки для службы, которую необходимо добавить в компонент установки.
2.
Щелкните любое место области конструктора.
3.
В области Описание окна Свойства щелкните ссылку Добавить установщик.
В проект будут добавлены новый класс ProjectInstaller и два компонента установки — ServiceProcessInstaller
и ServiceInstaller, а значения свойств службы будут скопированы в компоненты установки.
4.
Щелкните компонент ServiceInstaller и убедитесь в том, что значение свойства ServiceName компонента и
самой службы совпадают.
5.
Для определения способа запуска службы щелкните компонент ServiceInstaller и установите соответствующее значение свойства StartType.
Значение
Результат
Manual
После установки служба должна запускаться вручную. Дополнительные сведения см. в разделе Запуск служб.
Automatic
Служба будет запускаться сама при перезагрузке компьютера.
Disabled
Служба запускаться не будет.
Для определения контекста безопасности, в котором будет выполняться служба, щелкните компонент
ServiceProcessInstaller и установите соответствующие значения свойств. Дополнительные сведения см. в разделе Указание контекста безопасности для служб.
7.
Переопределите любые методы, требующиеся для реализации пользовательской обработки. Дополнительные
сведения см. в разделе Переопределение методов по умолчанию в компонентах установки.
8.
Для каждой дополнительной имеющейся в проекте службы повторите шаги с 1 по 6.
Примечание. Для каждой имеющейся в проекте дополнительной службы необходимо добавить дополнительный компонент ServiceInstaller в класс ProjectInstaller проекта. Компонент ServiceProcessInstaller, добавленный на шаге 3, работает со всеми имеющимися в проекте отдельными установщиками служб.
9.
Создайте проект установки, а также любые пользовательские действия, необходимые для развертывания и
установки службы. Дополнительные сведения о проектах установки см. в разделе Проекты установки. Дополнительные сведения о пользовательских действиях см. в разделе Пример. Создание пользовательского действия.
Определение контекста безопасности для служб
По умолчанию службы запускаются в контексте безопасности, отличающемся от контекста безопасности пользователя, вошедшего в систему. Службы запускаются в контексте системной учетной записи по умолчанию, называемой
LocalSystem, что дает им права доступа к системным ресурсам, отличающиеся от прав доступа для пользователя.
Чтобы изменить это поведение можно указать учетную запись пользователя, от имени которой будет запускаться
служба.
Контекст безопасности устанавливается путем изменения значения свойства Account для процесса, в котором выполняется служба. Это свойство позволяет запускать службу от имени четырех типов учетных записей.

User. При установке службы система запрашивает имя и пароль существующего пользователя. Служба будет
запускаться от имени учетной записи этого пользователя.
6.
9

LocalService. Служба выполняется в контексте учетной записи, аналогичной учетной записи непривилегированного пользователя текущего компьютера. Удаленным серверам при этом передаются учетные данные анонимного пользователя.

LocalSystem. Служба запускается от имени учетной записи, обеспечивающей обширные локальные права доступа. Удаленным серверам при этом передаются учетные данные текущего компьютера.

NetworkService. Служба выполняется в контексте учетной записи, аналогичной учетной записи непривилегированного пользователя текущего компьютера. Удаленным серверам передаются учетные данные текущего
компьютера.
Дополнительные сведения см. в разделе Перечисление ServiceAccount.
Чтобы указать контекст безопасности для службы
1.
Добавьте в служебное приложение необходимые установщики. Дополнительные сведения см. в разделе Добавление установщиков в служебное приложение.
2.
Для данной службы выберите в конструкторе класс ProjectInstaller и запустите установщик процессов службы.
Примечание. Для любого служебного приложения класс ProjectInstaller содержит по меньшей мере два установочных компонента — компонент, устанавливающий процессы для всех служб в проекте, и установщик для
каждой службы приложения. В этом случае следует выбрать ServiceProcessInstaller.
3.
В окне свойств присвойте свойству ServiceProcessInstaller.Account соответствующее значение.
Установка и удаление служб
В отличие от большинства проектов, создаваемых в Visual Studio .NET, проект службы Windows нельзя запустить на
выполнение непосредственно из среды разработки, нажав клавишу F5. Это происходит потому, что служба, содержащаяся в проекте, должна быть установлена до запуска проекта на выполнение.
Служебное приложение может быть установлено с помощью программы InstallUtil.exe. Можно также создать проект
установки, включающий результаты проекта, и задать действие, запускающее установщики, связанные с проектом и
устанавливающие службу. Пример. Создание служебного приложения Windows в конструкторе компонентов. Дополнительные сведения о проектах установки см. в разделе Проекты установки. Дополнительные сведения о пользовательских действиях см. в разделе Пример. Создание пользовательского действия.
Чтобы установить службу вручную
1.
Перейдите в папку, в которой размещается исполняемый файл, полученный в результате компиляции проекта.
2.
Из командной строки запустите программу InstallUtil.exe и передайте ей в качестве параметра выходные
файлы проекта. В командной строке введите следующую команду:
installutil yourproject.exe
Чтобы удалить службу вручную

Из командной строки запустите программу InstallUtil.exe и передайте ей в качестве параметра выходные
файлы проекта. В командной строке введите следующую команду:
installutil /u yourproject.exe
Совет Чтобы убедиться, что служба установлена или удалена, можно запустить обозреватель серверов.
Дополнительные сведения о запуске обозревателя серверов см. в разделе Получение доступа к обозревателю серверов и его инициализация.
Примечание. В обозревателе серверов узел Servers недоступен в стандартном выпуске Visual Basic и
Visual C# .NET. Дополнительные сведения см. в разделе Средства и возможности стандартного выпуска
Visual Basic или Средства и возможности стандартного выпуска Visual C#.
Запуск служб
После установки службы ее необходимо запустить. При запуске службы вызывается метод OnStart класса службы.
Как правило, метод OnStart определяет те функции, которые будет выполнять служба. После запуска служба остается активной до тех пор, пока она не будет вручную остановлена или приостановлена.
Службы могут быть настроены для автоматического запуска или для запуска вручную. Служба, настроенная для автоматического запуска, запускается при включении или перезагрузке компьютера, на котором она установлена.
Служба, настроенная для запуска вручную, должна запускаться самим пользователем.
Примечание. По умолчанию службы, созданные с помощью Visual Studio .NET, настроены для запуска вручную.
Существует несколько способов запустить службу вручную — из обозревателя серверов, из диспетчера управления
службами или непосредственно из программы при помощи компонента ServiceController. Дополнительные сведения
о компоненте ServiceController см. в разделе Наблюдение за службами Windows.
Настройка режима запуска службы
Чтобы определить, должна ли служба запускаться автоматически или вручную, необходимо установить значение
свойства StartType класса ServiceInstaller.
Чтобы настроить способ запуска службы
1.
Добавьте в служебное приложение необходимые установщики. Дополнительные сведения см. в разделе Добавление установщиков в служебное приложение.
2.
Для данной службы выберите в конструкторе установщик службы.
3.
В окне присвойте свойству StartType одно из следующих значений.
10
Режим запуска службы.
Значение свойства StartType
При запуске компьютера
Automatic
Вручную
Manual
4. Совет Чтобы запретить запуск службы установите для свойства StartType значение Disabled. Это может
понадобиться, например, при многократной перезагрузке сервера: запретив запуск некоторых служб, можно
уменьшить время перезагрузки.
5. Примечание. Значения свойства StartType и других свойств могут быть изменены после установки службы.
Запуск службы вручную
Существует несколько способов запуска службы, для которой процесс StartType установлен в значение Manual — с
помощью обозревателя серверов, с помощью диспетчера управления службами Windows или из программы. Необходимо отметить, что не все эти способы запускают службу в контексте диспетчера управления службами; обозреватель
серверов и методы программного запуска службы управляют контроллером.
Чтобы запустить службу вручную из обозревателя серверов
1.
В убедитесь, что нужный сервер присутствует в списке. Если его там нет, добавьте его в список. Дополнительные сведения см. в разделе Получение доступа к обозревателю серверов и его инициализация.
Примечание. В обозревателе серверов узел Servers недоступен в стандартном выпуске Visual Basic и Visual C#
.NET. Дополнительные сведения см. в разделе Возможности стандартного выпуска Visual Basic или Возможности стандартного выпуска Visual C#.
2.
Разверните узел Службы и выберите службу, которую необходимо запустить.
3.
Щелкните правой кнопкой мыши имя необходимой службы и выберите в появившемся меню команду
Начать.
Чтобы запустить службу вручную из диспетчера управления службами
1.
Откройте диспетчер управления службами. Для этого используйте один из следующих способов.

В Windows 2000 Professional щелкните правой кнопкой на рабочем столе значок Мой компьютер и
выберите пункт меню Управление. В появившемся окне раскройте узел Службы и приложения.
–или–

В Windows 2000 Server нажмите кнопку Пуск, выберите пункт Программы и Администрирование,
а затем выберите команду Службы.
Примечание. В Windows NT версии 4.0 это окно можно открыть из панели управления.
2.
В правой части окна содержится список служб.
3.
Выберите в списке необходимую службу, щелкните ее название правой кнопкой мыши и выберите в меню
команду Пуск.
Чтобы запустить службу вручную из программы
1.
Создайте экземпляр класса ServiceController и настройте его для взаимодействия с необходимой службой.
Дополнительные сведения см. в разделе Создание экземпляров компонентов ServiceController.
2.
Чтобы запустить службу, вызовите метод Пуск.
Отладка служебных приложений Windows
Поскольку служба должна выполняться из контекста диспетчера управления службами, а не из Visual Studio .NET,
отладка службы не является такой же простой задачей, как отладка других типов приложений Visual Studio. Для отладки службы необходимо запустить службу, а затем подключить отладчик к процессу, в котором она выполняется.
После этого можно отлаживать приложение с помощью стандартных средств отладки Visual Studio.
Внимание! Не следует подключаться к процессу, если неизвестна его природа и неясны последствия подключения и
возможного его уничтожения. Например, при подключении к процессу WinLogon и последующем прекращении отладки произойдет остановка системы, поскольку она не может работать без данного процесса.
Подключение отладчика можно производить только к выполняющейся службе. Процесс подключения прерывает текущую работу службы; при этом в действительности прекращения ее работы или остановки не происходит. Следовательно, если служба выполнялась в момент начала отладки, то в процессе отладки технически она все еще находится
в запущенном состоянии, однако ее работа приостанавливается.
Подключение к процессу службы позволяет отлаживать большую часть ее кода (но не весь код); поскольку служба
уже была запущена, невозможно, например, таким образом отладить код метода OnStart службы или код метода
Main, который используется для загрузки службы. Одним из способов обхода этого ограничения является создание в
служебном приложении второй (временной) службы, предназначенной только для помощи в отладке. Можно установить обе службы, а затем для загрузки процесса первой службы запустить эту вспомогательную службу. Сразу после
того как временная служба запустит процесс, для подключения к процессу службы можно воспользоваться меню Отладка Visual Studio .NET.
После подключения к процессу можно установить точки останова и использовать их для отладки кода. Работа с режимом отладки начинается сразу после выхода из диалогового окна, использованного для подключения к процессу.
Можно воспользоваться диспетчером управления службами для запуска, прекращения, остановки и продолжения
работы службы путем задания точек останова. Позднее, после успешной отладки приложения, эту «пустую» службу
можно удалить.
11
Примечание. Отладка метода OnStart может быть затруднена, поскольку в диспетчере служб Windows имеется 30секундное ограничение, распространяющееся на все попытки запуска служб. Дополнительные сведения см. в разделе
Устранение неполадок: отладка служб Windows.
Чтобы отладить службу
1.
Установите службу. Дополнительные сведения см. в разделе Установка и удаление служб.
2.
Запустите службу из диспетчера управления службами, обозревателя серверов или с помощью кода. Дополнительные сведения см. в разделе Запуск служб.
3.
В Visual Studio .NET выберите команду Процессы меню Отладка.
Будет отображено диалоговое окно Процессы.
4.
Нажмите Показать системные процессы.
5.
В разделе Имеющиеся процессы щелкните процесс службы и нажмите Присоединить.
Совет Процесс имеет то же имя, что и исполняемый файл службы.
Будет отображено диалоговое окно Присоединение к процессу.
6.
Выберите любые соответствующие параметры и нажмите OK для 1212закрытия диалогового окна.
Примечание. Теперь активирован режим отладки.
7.
Установите в коде любые нужные точки останова.
8.
Откройте диспетчер управления службами и поработайте со службой, отправляя ей команды прекращения,
остановки и продолжения, чтобы воспользоваться точками останова. Дополнительные сведения об использовании диспетчера управления службами см. в разделе Запуск служб.
Запись сведений о службах в журнал
По умолчанию все проекты служб Windows могут взаимодействовать с журналом событий приложения и записывать
в него информацию и исключения. Указать, требуется ли использовать в приложении эту возможность, можно с помощью свойства AutoLog. По умолчанию для всех служб, создаваемых с использованием шаблона проекта службы
Windows, включена возможность записи в журнал событий. Для записи информации в журнал можно использовать
статическую форму класса EventLog. При этом нет необходимости создавать экземпляр компонента EventLog или
регистрировать источник вручную.
Если возможность записи информации в журнал включена, то установщик службы автоматически регистрирует все
службы проекта как допустимые источники событий для журнала приложений на компьютере, на котором установлена служба. Служба делает запись в журнале при каждом запуске, остановке, приостановке, установке или удалении
службы. Кроме того, ведется запись сведений обо всех возникающих сбоях. При использовании поведения по умолчанию не требуется писать код для записи информации в журнал — служба делает это автоматически.
Если требуется делать запись в журналы, отличные от журнала приложений, необходимо установить свойство
AutoLog в значение false, создать в службе пользовательский журнал событий и зарегистрировать службу в качестве
источника записей для этого журнала. Дополнительные сведения см. в разделе Создание и удаление пользовательских журналов событий. Затем необходимо написать код, который будет производить запись в журнал всякий раз при
возникновении интересующего события.
Примечание. Если приложение настроено на использование пользовательского журнала событий, доступ к этому
журналу должен осуществляться только после установки значения для свойства ServiceName. Значение этого свойства необходимо журналу событий, чтобы зарегистрировать службу как источник событий.
Чтобы разрешить службе запись событий по умолчанию

Установите для компонента свойство AutoLog в значение true.
Примечание. По умолчанию для этого свойства задано значение true. Обычно нет необходимости в явной
установке значения этого свойства, хотя в некоторых случаях это может понадобиться — например, при установке значения свойства AutoLog в зависимости от выполнения какого-либо условия.
Чтобы запретить службе запись событий по умолчанию

Установите для компонента свойство AutoLog в значение false.

// C#
UserService1.AutoLog = false;
Чтобы настроить запись событий в пользовательский журнал
1.
Присвойте свойству AutoLog значение false.
Примечание. Установка свойства Autolog в значение false является обязательным условием использования
пользовательского журнала.
2.
В служебном приложении настройте экземпляр компонента EventLog. Дополнительные сведения см. в разделе Создание экземпляров компонентов EventLog.
3.
Создайте пользовательский журнал. Для этого вызовите метод CreateEventSource и укажите исходное расположение и имя создаваемого журнала.
4.
В экземпляре компонента EventLog присвойте свойству Source значение исходного расположения, созданное на шаге 3.
5.
Для выполнения записи в журнал используйте метод WriteEntry экземпляра компонента EventLog.
Следующий код показывает настройку записи в пользовательский журнал для Visual Basic и C#.
// C#
public UserService2()
12
{
this.AutoLog = false;
// create an event source, specifying the name of a log that
// does not currently exist to create a new, custom log
if (!System.Diagnostics.EventLog.SourceExists("MySource"))
{
System.Diagnostics.EventLog.CreateEventSource(
"MySource","MyLog");
}
// configure the event log instance to use this source name
eventLog1.Source = "MySource";
}
protected override void OnStart(string[] args)
{
// write an entry to the log
eventLog1.WriteEntry("In OnStart.");
}
Устранение неполадок: отладка служб Windows
При отладке служебного приложения Windows отлаживаемая служба взаимодействует с диспетчером служб
Windows. Диспетчер служб запускает службу, вызывая ее метод OnStart. После этого он в течение 30 секунд ожидает
ответа метода. Если в течение этого времени метод не возвращает никакого ответа, диспетчер служб выдает сообщение о невозможности запустить службу
При отладке метода OnStart, как описано в разделе Отладка служебных приложений Windows, необходимо учитывать этот 30-секундный интервал. Если поместить точку останова в методе OnStart и не пройти ее за 30 секунд, то
диспетчер служб не запустит отлаживаемую службу.
Устранение неполадок: служебное приложение не устанавливается
Если служебное приложение не устанавливается, следует убедиться, что свойству ServiceName класса приложения
присвоено то же самое значение, которое задано в установщике для этой службы. Для правильной установки службы
необходимо, чтобы это значение было одинаковым в обоих случаях.
Примечание. Для получения сведений о процессе установки можно также проанализировать журналы установки.
Необходимо также проверить, не установлена ли еще одна служба с таким же именем. Имена служб должны быть
уникальными.
13
Download