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


74

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

Answers:


41

看一下ServiceController类。

要执行重新启动服务时需要完成的操作,我想您应该在服务中自己进行(如果它是您自己的服务)。
如果您无权访问该服务的源,则可以使用的WaitForStatus方法ServiceController


1
这在服务本身内起作用吗?Windows服务可以以编程方式自行重启吗?
Paul Karam

76

本文使用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
  {
    // ...
  }
}

该解决方案的问题在于,就我而言,此操作需要管理员权限。而且我无法在运行时更改(指定)用户。
斯拉维克

@Slavik如果需要admin privs,那么采用哪种编程方式都没关系;您甚至可能甚至需要使用管理员级别的控制台来使用命令行工具,并且如果您通过任务管理器进行了尝试,则很可能会被拒绝访问。
kayleeFrye_onDeck

22

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

16

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

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

2
我喜欢这个答案,因为它不需要其他参考或帮助程序类。您可能想要添加.WaitForExit();。确保在再次启动之前已停止该服务: System.Diagnostics.Process.Start("net", "stop IISAdmin").WaitForExit(); System.Diagnostics.Process.Start("net", "start IISAdmin").WaitForExit();
Joris Talma,

10

该答案基于@Donut答案(该问题的最高投票答案),但进行了一些修改。

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

这是课程

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

6

怎么样

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

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

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


2

看这篇文章

这是文章的摘录。

//[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();
                }
        }
    }
}

15
在枚举上调用ToString()然后比较字符串而不是枚举有什么意义?
dzendras

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

1

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

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

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


-3

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

Environment.Exit(1);

我在服务中也做了同样的事情。一切正常。


服务重新启动时的操作如何?
法布里西奥·桑托斯

它的行为是正常的新起点。
2016年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.