C# 如何在 .NET 中以编程方式重新启动 Windows 服务

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1454502/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 17:42:58  来源:igfitidea点击:

How can I restart a windows service programmatically in .NET

c#windows-services

提问by Nemo

How can I restart a windows service programmatically in .NET?
Also, I need to do an operation when the service restart is completed.

如何在 .NET 中以编程方式重新启动 Windows 服务?
另外,我需要在服务重启完成后做一个操作。

采纳答案by Frederik Gheysels

Take a look at the ServiceControllerclass.

查看ServiceController类。

To perform the operation that needs to be done when the service is restarted, I guess you should do that in the Service yourself (if it is your own service).
If you do not have access to the source of the service, then perhaps you can use the WaitForStatusmethod of the ServiceController.

执行服务重启时需要做的操作,我猜你应该自己在Service里面做(如果是你自己的服务)。
如果您没有访问该服务的来源,那么也许你可以使用WaitForStatus的方法ServiceController

回答by Donut

This articleuses the ServiceControllerclass to write methods for Starting, Stopping, and Restarting Windows services; it might be worth taking a look at.

本文使用ServiceController该类编写启动、停止和重新启动 Windows 服务的方法;可能值得一看。

Snippet from the article (the "Restart Service" method):

文章摘录(“重启服务”方法):

public static void RestartService(string serviceName, int timeoutMilliseconds)
{
  ServiceController service = new ServiceController(serviceName);
  try
  {
    int millisec1 = Environment.TickCount;
    TimeSpan timeout = TimeSpan.FromMilliseconds(timeoutMilliseconds);

    service.Stop();
    service.WaitForStatus(ServiceControllerStatus.Stopped, timeout);

    // count the rest of the timeout
    int millisec2 = Environment.TickCount;
    timeout = TimeSpan.FromMilliseconds(timeoutMilliseconds - (millisec2-millisec1));

    service.Start();
    service.WaitForStatus(ServiceControllerStatus.Running, timeout);
  }
  catch
  {
    // ...
  }
}

回答by David Basarab

See this article.

请参阅这篇文章

Here is a snippet from the article.

这是文章的一个片段。

//[QUICK CODE] FOR THE IMPATIENT
using System;
using System.Collections.Generic;
using System.Text;
// ADD "using System.ServiceProcess;" after you add the 
// Reference to the System.ServiceProcess in the solution Explorer
using System.ServiceProcess;
namespace Using_ServiceController{
    class Program{
        static void Main(string[] args){
            ServiceController myService = new ServiceController();
            myService.ServiceName = "ImapiService";
            string svcStatus = myService.Status.ToString();
                if (svcStatus == "Running"){
                    myService.Stop();
                }else if(svcStatus == "Stopped"){
                    myService.Start();
                }else{
                    myService.Stop();
                }
        }
    }
}

回答by Johnno Nolan

How about

怎么样

var theController = new System.ServiceProcess.ServiceController("IISAdmin");

theController.Stop();
theController.Start();

Don't forget to add the System.ServiceProcess.dll to your project for this to work.

不要忘记将 System.ServiceProcess.dll 添加到您的项目中以使其正常工作。

回答by Druid

You could also call the netcommand to do this. Example:

您也可以调用net命令来执行此操作。例子:

System.Diagnostics.Process.Start("net", "stop IISAdmin");
System.Diagnostics.Process.Start("net", "start IISAdmin");

回答by ionat

An example using by ServiceController Class

ServiceController 类使用的示例

private void RestartWindowsService(string serviceName)
{
    ServiceController serviceController = new ServiceController(serviceName);
    try
    {
        if ((serviceController.Status.Equals(ServiceControllerStatus.Running)) || (serviceController.Status.Equals(ServiceControllerStatus.StartPending)))
        {
            serviceController.Stop();
        }
        serviceController.WaitForStatus(ServiceControllerStatus.Stopped);
        serviceController.Start();
        serviceController.WaitForStatus(ServiceControllerStatus.Running);
    }
    catch
    {
        ShowMsg(AppTexts.Information, AppTexts.SystematicError, MessageBox.Icon.WARNING);
    }
}

回答by Sid

Call Environment.Exitwith an error code greater than 0, which seems appropriate, then on install we configure the service to restart on error.

Environment.Exit使用大于 0 的错误代码调用,这似乎是合适的,然后在安装时我们将服务配置为在错误时重新启动。

Environment.Exit(1);

I have done same thing in my Service. It is working fine.

我在我的服务中做了同样的事情。它工作正常。

回答by Hakan F?st?k

This answer is based on @Donut Answer (the most up-voted answer of this question), but with some modifications.

这个答案基于@Donut Answer(这个问题中投票最多的答案),但做了一些修改。

  1. Disposing of ServiceControllerclass after each use, because it implements IDisposableinterface.
  2. Reduce the parameters of the method: there is no need to the serviceNameparameter being passed for each method, we can set it in the constructor, and each other method will use that service name.
    This is also more OOP friendly.
  3. Handle the catch exception in a way that this class could be used as a component.
  4. Remove the timeoutMillisecondsparameter from each method.
  5. Add two new methods StartOrRestartand StopServiceIfRunning, which could be considered as a wrapper for other basic methods, The purpose of those methods are only to avoid exceptions, as described in the comment.
  1. ServiceController每次使用后处理类,因为它实现了IDisposable接口。
  2. 减少方法的参数:不需要serviceName为每个方法传递参数,我们可以在构造函数中设置它,每个其他方法都会使用该服务名称。
    这也更加 OOP 友好。
  3. 以此类可用作组件的方式处理 catch 异常。
  4. timeoutMilliseconds从每个方法中删除参数。
  5. 添加两个新方法StartOrRestartand StopServiceIfRunning,它们可以被认为是其他基本方法的包装器,这些方法的目的只是为了避免异常,如注释中所述。

Here is the class

这是课堂

public class WindowsServiceController
{
    private string serviceName;

    public WindowsServiceController(string serviceName)
    {
        this.serviceName = serviceName;
    }

    // this method will throw an exception if the service is NOT in Running status.
    public void RestartService()
    {
        using (ServiceController service = new ServiceController(serviceName))
        {
            try
            {
                service.Stop();
                service.WaitForStatus(ServiceControllerStatus.Stopped);

                service.Start();
                service.WaitForStatus(ServiceControllerStatus.Running);
            }
            catch (Exception ex)
            {
                throw new Exception($"Can not restart the Windows Service {serviceName}", ex);
            }
        }
    }

    // this method will throw an exception if the service is NOT in Running status.
    public void StopService()
    {
        using (ServiceController service = new ServiceController(serviceName))
        {
            try
            {
                service.Stop();
                service.WaitForStatus(ServiceControllerStatus.Stopped);
            }
            catch (Exception ex)
            {
                throw new Exception($"Can not Stop the Windows Service [{serviceName}]", ex);
            }
        }
    }

    // this method will throw an exception if the service is NOT in Stopped status.
    public void StartService()
    {
        using (ServiceController service = new ServiceController(serviceName))
        {
            try
            {
                service.Start();
                service.WaitForStatus(ServiceControllerStatus.Running);
            }
            catch (Exception ex)
            {
                throw new Exception($"Can not Start the Windows Service [{serviceName}]", ex);
            }
        }
    }

    // if service running then restart the service if the service is stopped then start it.
    // this method will not throw an exception.
    public void StartOrRestart()
    {
        if (IsRunningStatus)
            RestartService();
        else if (IsStoppedStatus)
            StartService();
    }

    // stop the service if it is running. if it is already stopped then do nothing.
    // this method will not throw an exception if the service is in Stopped status.
    public void StopServiceIfRunning()
    {
        using (ServiceController service = new ServiceController(serviceName))
        {
            try
            {
                if (!IsRunningStatus)
                    return;

                service.Stop();
                service.WaitForStatus(ServiceControllerStatus.Stopped);
            }
            catch (Exception ex)
            {
                throw new Exception($"Can not Stop the Windows Service [{serviceName}]", ex);
            }
        }
    }

    public bool IsRunningStatus => Status == ServiceControllerStatus.Running;

    public bool IsStoppedStatus => Status == ServiceControllerStatus.Stopped;

    public ServiceControllerStatus Status
    {
        get
        {
            using (ServiceController service = new ServiceController(serviceName))
            {
                return service.Status;
            }
        }
    }
}

回答by Johny Wave

I needed somethin more complex, because sometimes services with depencies couldnt be restarted and just throw exception or service could be set to "disabled" and so on.

我需要更复杂的东西,因为有时无法重新启动具有依赖项的服务,只能抛出异常或服务可以设置为“禁用”等等。

So this is what i did:

所以这就是我所做的:

(It checks if service does exist, if its "Disabled" it will set service to "Auto" and when it couldnt restart service it will use taskkill command to kill service through PID and then start it again (You need to be carefull with dependent services with this cause you will need to start/restart them too).

(它检查服务是否确实存在,如果它“已禁用”,它会将服务设置为“自动”,当它无法重新启动服务时,它将使用 taskkill 命令通过 PID 终止服务,然后重新启动它(你需要小心依赖出于此原因的服务,您也需要启动/重新启动它们)。

And it just returns true/false if restart was sucessfull

如果重新启动成功,它只会返回真/假

Tested on WIN10 only.

仅在 WIN10 上测试。

PS: working on version which detect dependent services when using taskkill and restart them too

PS:在使用 taskkill 时检测依赖服务并重新启动它们的版本上工作

//Get windows service status
    public static string GetServiceStatus(string NameOfService)
    {
        ServiceController sc = new ServiceController(NameOfService);

        switch (sc.Status)
        {
            case ServiceControllerStatus.Running:
                return "Running";
            case ServiceControllerStatus.Stopped:
                return "Stopped";
            case ServiceControllerStatus.Paused:
                return "Paused";
            case ServiceControllerStatus.StopPending:
                return "Stopping";
            case ServiceControllerStatus.StartPending:
                return "Starting";
            default:
                return "Status Changing";
        }
    }

    //finds if service exists in OS
    public static bool DoesServiceExist(string serviceName)
    {
        return ServiceController.GetServices().Any(serviceController => serviceController.ServiceName.Equals(serviceName));
    }

    //finds startup type of service
    public static string GetStartupType(string serviceName)
    {
        ManagementObject objManage = new ManagementObject("Win32_Service.Name='"+serviceName+"'");
        objManage.Get();

        string status1 = objManage["StartMode"].ToString();

        return status1;
    }

    //restart service through PID
    public static bool RestartServiceByPID(string NameOfService)
    {
        LogWriter log = new LogWriter("TaskKilling: " + NameOfService);

        string strCmdText = "/C taskkill /f /fi \"SERVICES eq " + NameOfService + "\"";
        Process.Start("CMD.exe", strCmdText);

        using(ServiceController ScvController = new ServiceController(NameOfService))
        {
            ScvController.WaitForStatus(ServiceControllerStatus.Stopped);

            if (GetServiceStatus(NameOfService) == "Stopped")
            {
                ScvController.Start();
                ScvController.WaitForStatus(ServiceControllerStatus.Running);

                if (GetServiceStatus(NameOfService) == "Running")
                {
                    return true;
                }
                else
                {
                    return false;
                }

            }
            else
            {
                return false;
            }
        }
    }

    //Restart windows service
    public static bool RestartWindowsService(string NameOfService)
    {

        try
        {
            //check if service exists
            if(DoesServiceExist(NameOfService) == false)
            {
                MessageBox.Show("Service " + NameOfService + " was not found.");
                return false;
            }
            else
            {
                //if it does it check startup type and if it is disabled it will set it to "Auto"
                if (GetStartupType(NameOfService) == "Disabled")
                {
                    using (var svc = new ServiceController(NameOfService))
                    {
                        ServiceHelper.ChangeStartMode(svc, ServiceStartMode.Automatic);

                        if (svc.Status != ServiceControllerStatus.Running)
                        {
                            svc.Start();
                            svc.WaitForStatus(ServiceControllerStatus.Running);

                            if(GetServiceStatus(NameOfService) == "Running")
                            {
                                return true;
                            }
                            else
                            {
                                return false;
                            }
                        }
                        else
                        {
                            svc.Stop();
                            svc.WaitForStatus(ServiceControllerStatus.Stopped);

                            if(GetServiceStatus(NameOfService) == "Stopped")
                            {
                                svc.Start();
                                svc.WaitForStatus(ServiceControllerStatus.Running);

                                if(GetServiceStatus(NameOfService) == "Running")
                                {
                                    return true;
                                }
                                else
                                {
                                    return false;
                                }
                            }
                            //restart through PID
                            else
                            {
                                return RestartServiceByPID(NameOfService);
                            }
                        }

                    }
                }
                //If service is not disabled it will restart it
                else
                {
                    using(ServiceController ScvController = new ServiceController(NameOfService))
                    {
                        if(GetServiceStatus(NameOfService) == "Running")
                        {

                            ScvController.Stop();
                            ScvController.WaitForStatus(ServiceControllerStatus.Stopped);

                            if(GetServiceStatus(NameOfService) == "Stopped")
                            {
                                ScvController.Start();
                                ScvController.WaitForStatus(ServiceControllerStatus.Running);

                                if(GetServiceStatus(NameOfService) == "Running")
                                {
                                    return true;
                                }
                                else
                                {
                                    return false;
                                }

                            }
                            //if stopping service fails, it uses taskkill
                            else
                            {
                                return RestartServiceByPID(NameOfService);
                            }
                        }
                        else
                        {
                            ScvController.Start();
                            ScvController.WaitForStatus(ServiceControllerStatus.Running);

                            if(GetServiceStatus(NameOfService) == "Running")
                            {
                                return true;
                            }
                            else
                            {
                                return false;
                            }

                        }
                    }
                }
            }
        }
        catch(Exception ex)
        {
            return RestartServiceByPID(NameOfService);
        }
    }

回答by Dafydd

You can set a service to restart after failure. So a restart can be forced by throwing an exception.

您可以将服务设置为失败后重新启动。所以可以通过抛出异常来强制重启。

Use recovery tab on service properties.

使用服务属性上的恢复选项卡。

Be sure to use reset fail count property to prevent service stopping altogether.

请务必使用重置失败计数属性来防止服务完全停止。