簡體   English   中英

如何在 .NET 中以編程方式重新啟動 Windows 服務

[英]How can I restart a windows service programmatically in .NET

如何在 .NET 中以編程方式重新啟動 Windows 服務?
另外,我需要在服務重啟完成后做一個操作。

本文使用ServiceController類來編寫Starting、Stopping和Restarting 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
  {
    // ...
  }
}

查看ServiceController類。

執行服務重啟時需要做的操作,我猜你應該自己在Service里面做(如果是你自己的服務)。
如果您無權訪問服務的源代碼,那么也許您可以使用ServiceControllerWaitForStatus方法。

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

您也可以調用net命令來執行此操作。 例子:

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

這個答案基於@Donut Answer(這個問題中投票最多的答案),但做了一些修改。

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

怎么樣

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

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

不要忘記將 System.ServiceProcess.dll 添加到您的項目中以使其正常工作。

請參閱這篇文章

這是文章的一個片段。

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

我需要更復雜的東西,因為有時無法重新啟動具有依賴項的服務,只能拋出異常或服務可以設置為“禁用”等等。

所以這就是我所做的:

(它檢查服務是否確實存在,如果它“已禁用”,它會將服務設置為“自動”,當它無法重新啟動服務時,它將使用 taskkill 命令通過 PID 終止服務,然后重新啟動它(你需要小心依賴出於此原因的服務,您也需要啟動/重新啟動它們)。

如果重新啟動成功,它只會返回真/假

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

您可以將服務設置為失敗后重新啟動。 所以可以通過拋出異常來強制重啟。

使用服務屬性上的恢復選項卡。

請務必使用重置失敗計數屬性來防止服務完全停止。

使用大於 0 的錯誤代碼調用Environment.Exit ,這似乎合適,然后在安裝時我們將服務配置為在錯誤時重新啟動。

Environment.Exit(1);

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM