Архитектура служб Windows

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

§  приложение, реализующее функциональность одной или нескольких служб (приложение-служба);

§  приложение, управляющее поведением службы (приложение-контроллер службы);

§  Service Control Manager – утилита, используемая для управления зарегистрированными на компьютере службами.

Список всех зарегистрированных служб расположен в реестре Windows в разделе:

HKEY_LOCAL_MACHINE | SYSTEM | CurrentControlSet | Services.

Служба может находиться в состоянии: работает, остановлена, приостановлена.

Служба может выполняться в отдельном процессе (Win32OwnProcess) или в процессе совместно с другими службами (Win32ShareProcess).

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

Для создания служб, установки и управления службами предназначены классы из пространства имен System.ServiceProcess.

Создать службу можно, используя методы класса ServiceBase.

Регистрация служб в системном реестре выполняется методами классов ServiceInstaller (устанавливает класс службы) и ServiceProcessInstaller (создает процесс, в котором будет выполняться служба).

Для запуска и остановки службы используются методы класса ServiceController.

Классы пространства имен System.Diagnostics предназначены для отслеживания и отладки служб:

§  класс EventLog – позволяет службе заносить информацию об ошибках в журнал событий;

§  класс PerfomanceCounter – позволяет отслеживать используемость ресурсов;

§  класс Trace – позволяет выполнять трассировку службы.

§  класс Debug –  предназначается для отладки служб.

Методы базового класса создаваемой службы System.ServiceProcess.ServiceBase:

§  OnStart – вызывается при запуске службы;

§  OnPause – вызывается при приостановке службы;

§  OnStop – вызывается при останове службы;

§  OnContinue – вызывается при возобновлении работы службы;

§  OnShutDown – вызывается при выключении ПК;

§  OnCustomCommand – вызывается для обработки пользовательских команд, информация о команде указывается параметрами;

§  OnPowerEvent – вызывается при получении сообщения от службы управления питанием.

Переопределение методов класса System.ServiceProcess.ServiceBase позволяет определить поведение службы.

Методы класса System.ServiceProcess.ServiceController, используемые для программного управления службой:

§  Close – отключает экземпляр класса ServiceController от службы и освобождает все ресурсы, занятые службой;

§  Continue – возобновляет работу службы;

§  ExecuteCommand – передает службе произвольную команду;

§  Pause – приостанавливает службу;

§  Refresh – обновляет значения всех свойств;

§  Start – запускает службу;

§  Stop – останавливает службу, а также все зависимые от нее другие службы.

 

Для создания служб можно использовать шаблон Windows Service.

Далее следует:

1.Установить следующие свойства службы: ServiceName – имя службы для SCM, Name – имя класса службы.

2.Дополнительно можно изменить следующие свойства службы: CanStop – можно ли останавливать службу после запуска, CanPauseAndContinue, CanShutdown, AutoLog – позволяет службе использовать системный журнал событий (при значении равном false используются собственные журналы событий).

3.Переопределить методы обработки событий: OnStart и OnStop.

4. 

Запуск службы

При запуске службы SCM инициирует вызов метода OnStart в найденном системой exe-файле. Свойство StartType позволяет указать автоматический запуск службы при загрузке ПК. Перечисление ServiceStartMode предоставляет следующие значения: Automatic, Manual, Disabled.

Событие OnStop передается службе в том случае, если значение свойства CanStop равно true.

Журнал событий

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

По умолчанию разрешается записывать информацию в журналы:

System, Security иApplication.

Например:

  // DBWriter – имя службы и имя класса службы

   public class DBWriter : System.ServiceProcess.ServiceBase

   {    // Журнал событий:

      private System.Diagnostics.EventLog eventLog1;

      // Счетчик производительности (Отображаются на вкладке Servers

     // в разделе PerformanceCounter

      private System.Diagnostics.PerformanceCounter perfCounter1;

      private System.ComponentModel.Container components = null;

      public DBWriter()            {          InitializeComponent();                       }

      static void Main()

      {    System.ServiceProcess.ServiceBase[] ServicesToRun;

         ServicesToRun = new System.ServiceProcess.ServiceBase[] {

                                                                                    new DBWriter() };

         System.ServiceProcess.ServiceBase.Run(ServicesToRun);   // Запуск

                                                                                                           // сервиса

      }

      private void InitializeComponent()

      { this.eventLog1 = new System.Diagnostics.EventLog();

         this.perfCounter1 =  new System.Diagnostics.PerformanceCounter();

         ((System.ComponentModel.ISupportInitialize)(this.eventLog1)).BeginInit();

    ((System.ComponentModel.ISupportInitialize)(this.perfCounter1)).BeginInit();

         // eventLog1:

         this.eventLog1.Log = "Trans Log";  // Имя файла журнала событий

         this.eventLog1.Source = "Trans Service"; 

         // perfCounter1:

         this.perfCounter1.CategoryName = "MyCounters";

         this.perfCounter1.CounterName = "Ctr1";

         this.perfCounter1.ReadOnly = false;

                 // Увеличение значения счетчика с шагом 4:

                 //perfCounter1.Increment(4);

                // Уменьшение счетчика с шагом 3: perfCounter1.Decrement(3);

                // Установка значения счетчика равным 10:

                // perfCounter1.RawValue=10;

               // Получение значения счетчика: int i1=perfCounter1.RawValue;

         // Сервис DBWriter:

         this.AutoLog = false;

         this.ServiceName = "DBWriter";

         ((System.ComponentModel.ISupportInitialize)(this.eventLog1)).EndInit();

   ((System.ComponentModel.ISupportInitialize)(this.performanceCounter1)).EndInit();

      }

      protected override void Dispose( bool disposing )

      {    if( disposing )  {if (components != null) { components.Dispose(); }           }

         base.Dispose( disposing );

      }

      protected override void OnStart(string[] args)

      {

         // Создаем и закрываем файл Log.tmp

         FileStream tfs = File.Create("C:\\Log.tmp");

         tfs.Close();

         // Если не существует, то создаем файл Customers.db

         if  (!File.Exists("C:\\Customers.db"))

         {FileStream cfs= File.Create("C:\\Customers.db");

         cfs.Close();

         }

         //  Записываем данные( entry) в log-файл событий

         eventLog1.WriteEntry("DBWriter сервис запущен в " +

                                                  System.DateTime.Now.ToString());

      }

      protected override void OnStop()

      {

          // Удаляем файл Log.tmp

        File.Delete("C:\\Log.tmp");

        // Устанавливаем значение счетчика производительности равным  0

        perfCounter1.RawValue = 0;

        // Записываем данные в log-файл

        eventLog1.WriteEntry("DBWriter сервис остановлен в " +

                                                          System.DateTime.Now.ToString());

      }

      protected override void OnCustomCommand(int command)

      {

         if (command == 201)     Commit();

            else if (command == 200) Rollback();

      }

      private void Commit()

      {

         // Создаем для чтения данных из  Log.tmp поток StreamReader

         StreamReader sr =

                       new StreamReader(new FileStream("C:\\Log.tmp",

                                                                                 FileMode.Open));

         // Созаем для записи данных в  Customers.db поток  StreamWriter

         StreamWriter sw =

                       new StreamWriter(new FileStream("C:\\Customers.db",

                                                                               FileMode.Append,

                                                                               FileAccess.Write));

         sw.WriteLine(sr.ReadToEnd());

         sw.Flush();

         //Закрываем файлы

         sr.Close();

         sw.Close();

         //Увеличиваем счетчик и записываем вход в  EventLog

         perfCounter1.Increment();

         truncateLogFile();

         eventLog1.WriteEntry("DBWriter сервис завиксировал транзакцию в " +

                                            System.DateTime.Now.ToString());

      }

      private void Rollback()

      { truncateLogFile();

        eventLog1.WriteEntry("DBWriter сервис выполнил откат транзакции в" +

                                              System.DateTime.Now.ToString());

      }

      private void truncateLogFile()

      { // Удаляем данные из файла Log.tmp

         FileStream fs =new FileStream("C:\\Log.tmp", FileMode.Truncate);

         fs.Flush();

         fs.Close();

      }

   }

}

 

Установка Службы

Для установки службы используются установочные компоненты, реализуемые классами:

§  System.ServiceProcess.ServiceProcessInstaller – один экземпляр на процесс;

§  System.ServiceProcess.ServiceInstaller – один экземпляр на каждую службу процесса;

§  System.Diagnostics.EventLogInstaller – для настройки объектов журналов событий;

§  System.Diagnostics.PerformanceCounterInstaller – для настройки счетчиков производительности.

 

Класс, используемый для установки службы должен наследоваться от System.Configuration.Install.Installer.

 

Для настройки контекста безопасности используется свойство Account класса ServiceProcessInstaller, которое может принимать следующие значения:

§  LocalService – учетная запись, обладающая расширенным набором прав на локальном ПК и предоставляющая учетные данные компьютера другим пользователям;

§  LocalSystem – учетная запись пользователя с ограниченными правами на локальном компьютере, предоставляющая учетные данные анонимного пользователя удаленным серверам;

§  NetworkService – учетная запись пользователя с ограниченными правами на локальном компьютере, предоставляющая учетные данные удаленным серверам;

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

 

После добавления к приложению установочных компонентов и компиляции, полученный exe-файл следует установить,  выполнив команду:

                 Instalutil   имя_службы.exe

Для удаления службы следует выполнить:

                 Instalutil  /u    имя_службы.exe

 

Управление службами выполняется:

§ интерактивно посредством SCM;

§ программно при помощи класса ServiceController.

Вы можете следить за любыми ответами на эту запись через RSS 2.0 ленту. Вы можете оставить ответ, или trackback с вашего собственного сайта.

Оставьте отзыв

XHTML: Вы можете использовать следующие теги: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

 
Rambler's Top100