Управление службами Windows

39

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

Start()

Метод start() указывает SCM, что требуется запустить службу. В рассматриваемом примере программы службы вызывается метод OnStart().

Stop()

Метод stop() с помощью SCM вызывает в рассматриваемом примере программы службы метод OnStop() в случае, если свойство CanStop службы имеет значение true.

Pause()

Метод Pause() вызывает метод OnPause() в случае, если свойство CanPauseAndContinue имеет значение true.

Continue()

Метод Continue() вызывает метод OnContinue() в случае, если свойство CanPauseAndContinue имеет значение true.

ExecuteCommand()

Метод ExecuteCommand() позволяет посылать службе специальные команды.

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

protected void OnServiceCommand(object sender, RoutedEventArgs e)
        {
            Cursor oldCursor = this.Cursor;
            try
            {
                this.Cursor = Cursors.Wait;
                ServiceControllerInfo si =
                       (ServiceControllerInfo)listBoxServices.SelectedItem;
                if (sender == this.buttonStart)
                {
                    si.Controller.Start();
                    si.Controller.WaitForStatus(ServiceControllerStatus.Running, TimeSpan.FromSeconds(10));
                }
                else if (sender == this.buttonStop)
                {
                    si.Controller.Stop();
                    si.Controller.WaitForStatus(ServiceControllerStatus.Stopped, TimeSpan.FromSeconds(10));
                }
                else if (sender == this.buttonPause)
                {
                    si.Controller.Pause();
                    si.Controller.WaitForStatus(ServiceControllerStatus.Paused, TimeSpan.FromSeconds(10));
                }
                else if (sender == this.buttonContinue)
                {
                    si.Controller.Continue();
                    si.Controller.WaitForStatus(ServiceControllerStatus.Running, TimeSpan.FromSeconds(10));
                }
                int index = listBoxServices.SelectedIndex;
                RefreshServiceList();
                listBoxServices.SelectedIndex = index;
            }
            catch (System.ServiceProcess.TimeoutException ex)
            {
                MessageBox.Show(ex.Message, "Timeout Service Controller", MessageBoxButton.OK, MessageBoxImage.Error);
            }
            catch (InvalidOperationException ex)
            {
                MessageBox.Show(String.Format("{0} {1}", ex.Message, ex.InnerException != null ? ex.InnerException.Message : String.Empty),
                    "Error Service Controller", MessageBoxButton.OK, MessageBoxImage.Error);
            }
            finally
            {
                this.Cursor = oldCursor;
            }
        }

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

Поскольку для запуска приложения требуются административные привилегии, как и для запуска и останова большинства служб, в проект добавлен манифест приложения, в котором для requestedExecutionLevel установлено значение requireAdministrator:

<?xml version="1.0" encoding="utf-8"?>
<asmv1:assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
    <security>
      <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">

        <requestedExecutionLevel  level="asInvoker" uiAccess="false" />
        <requestedExecutionLevel  level="requireAdministrator" uiAccess="false" />
        <requestedExecutionLevel  level="highestAvailable" uiAccess="false" />
        <requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
      </requestedPrivileges>
    </security>
  </trustInfo>
</asmv1:assembly>

Ниже показано работающее приложение:

Мониторинг служб в приложении WPF
Пройди тесты
Лучший чат для C# программистов