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

时间:2009-09-21 13:27:17

标签: c# windows-services

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

10 个答案:

答案 0 :(得分:69)

This article使用ServiceController类编写启动,停止和重新启动Windows服务的方法;可能值得一看。

文章中的片段(“重新启动服务”方法):

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
  {
    // ...
  }
}

答案 1 :(得分:36)

查看ServiceController课程。

要执行重新启动服务时需要执行的操作,我想您应该自己在服务中执行此操作(如果它是您自己的服务)。
如果您无权访问该服务的来源,那么您可以使用WaitForStatus的{​​{1}}方法。

答案 2 :(得分:22)

ServiceController Class

使用的示例
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);
    }
}

答案 3 :(得分:15)

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

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

答案 4 :(得分:7)

这个答案是基于@Donut答案(这个问题的最高投票答案),但有一些修改。

  1. 每次使用后处置ServiceController类,因为它实现了IDisposable接口。
  2. 减少方法的参数:不需要为每个方法传递serviceName参数,我们可以在构造函数中设置它,并且每个其他方法将使用该服务名称。
    这也更加友好。
  3. 以此类可用作组件的方式处理catch异常。
  4. 从每种方法中删除timeoutMilliseconds参数。
  5. 添加两个新方法StartOrRestartStopServiceIfRunning,它们可以被视为其他基本方法的包装器。这些方法的目的只是为了避免异常,如注释中所述。
  6. 这是班级

    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;
                }
            }
        }
    }
    

答案 5 :(得分:6)

怎么样

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

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

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

答案 6 :(得分:2)

请参阅此article

以下是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();
                }
        }
    }
}

答案 7 :(得分:1)

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

这就是我所做的:

(它检查服务是否确实存在,如果它的“ Disabled”将其设置为“ Auto”,当它无法重新启动服务时,它将使用taskkill命令通过PID终止服务,然后再次启动它(您需要谨慎使用相关服务,这也将导致您也需要启动/重新启动它们。

如果重新启动成功,它只会返回true / false

仅在WIN10上测试。

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);
        }
    }

答案 8 :(得分:0)

您可以将服务设置为在失败后重新启动。因此,可以通过引发异常来强制重新启动。

使用服务属性上的恢复标签。

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

答案 9 :(得分:-3)

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

Environment.Exit(1);

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