Как программно остановить службу Windows
О программировании служб Windows: как остановить службу Windows?
Вот очень упрощенный пример кода (С#):
// Here is my service class (MyTestService.cs).
public class MyTestService:ServiceBase{
// Constructor.
public MyTestService(){
this.ServiceName = "My Test Service";
return;
}
};
// My application class (ApplicationClass.cs).
public static class ApplicationClass{
// Here is main Main() method.
public static void Main(){
// 1. Creating a service instance
// and running it using ServiceBase.
MyTestService service = new MyTestService();
ServiceBase.Run(service);
// 2. Performing a test shutdown of a service.
service.Stop();
Environment.Exit(0);
return;
};
};
Итак: я только что создал "My Test Service", начал его и остановился. Но когда я просматриваю свои Services.msc - "Моя тестовая служба" продолжает работать и останавливается ТОЛЬКО, когда я нажимаю ссылку "Стоп". Зачем? - почему команда service.Stop() ничего не делает?
ServiceController.Stop() также ничего не делает!
Как остановить службу из метода Main()?
Ответы
Ответ 1
Функция Stop
отправляет сигнал остановки. Он не дожидается, пока сигнал будет принят и обработан.
Вам придется подождать, пока Stop-сигнал не заработает. Вы можете сделать это, вызвав WaitForStatus
:
service.Stop();
service.WaitForStatus(ServiceControllerStatus.Stopped);
См. дополнительную информацию: http://msdn.microsoft.com/nl-nl/library/system.serviceprocess.servicecontroller.waitforstatus(v=vs.71).aspx
Environment.Exit
является неприятным. НЕ ИСПОЛЬЗУЙТЕ ЭТО! Он прервет ваше приложение жестким способом, не выполняя никакой очистки в окончательных блоках, не вызывая методы finalizer GC, он завершает все другие фоновые потоки и т.д. Я могу представить, что ваше приложение отменено до того, как сигнал останова даже покинул ваше приложение.
Ответ 2
Я использую следующие функции в моем проекте
public static ServiceController GetService(string serviceName)
{
ServiceController[] services = ServiceController.GetServices();
return services.FirstOrDefault(_ => Contracts.Extensions.CompareStrings(_.ServiceName, serviceName));
}
public static bool IsServiceRunning(string serviceName)
{
ServiceControllerStatus status;
uint counter = 0;
do
{
ServiceController service = GetService(serviceName);
if (service == null)
{
return false;
}
Thread.Sleep(100);
status = service.Status;
} while (!(status == ServiceControllerStatus.Stopped ||
status == ServiceControllerStatus.Running) &&
(++counter < 30));
return status == ServiceControllerStatus.Running;
}
public static bool IsServiceInstalled(string serviceName)
{
return GetService(serviceName) != null;
}
public static void StartService(string serviceName)
{
ServiceController controller = GetService(serviceName);
if (controller == null)
{
return;
}
controller.Start();
controller.WaitForStatus(ServiceControllerStatus.Running);
}
public static void StopService(string serviceName)
{
ServiceController controller = GetService(serviceName);
if (controller == null)
{
return;
}
controller.Stop();
controller.WaitForStatus(ServiceControllerStatus.Stopped);
}
Ответ 3
В ваших примерах кода service.Stop()
и ServiceController.Stop()
команды ничего не делают, потому что они не вызываются во время работы службы, поскольку ServiceBase.Run(service)
блокирует операцию и возвращается только при остановке службы.