Как программно остановить службу 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) блокирует операцию и возвращается только при остановке службы.