Управление службами Windows
39C# и .NET --- Основы .NET --- Управление службами Windows
С помощью класса 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>
Ниже показано работающее приложение: