【发布时间】:2023-03-08 04:35:01
【问题描述】:
如何在 .NET 中以编程方式重新启动 Windows 服务?
另外,我需要在服务重启完成后进行操作。
【问题讨论】:
标签: c# windows-services
如何在 .NET 中以编程方式重新启动 Windows 服务?
另外,我需要在服务重启完成后进行操作。
【问题讨论】:
标签: c# windows-services
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
{
// ...
}
}
【讨论】:
看看ServiceController 类。
要执行重启服务时需要做的操作,我猜你应该在Service中自己做(如果是你自己的服务)。
如果您无权访问服务源,那么也许您可以使用ServiceController 的WaitForStatus 方法。
【讨论】:
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");
【讨论】:
System.Diagnostics.Process.Start("net", "stop IISAdmin").WaitForExit();System.Diagnostics.Process.Start("net", "start IISAdmin").WaitForExit();
此答案基于@Donut 答案(该问题投票最多的答案),但有一些修改。
ServiceController 类,因为它实现了IDisposable 接口。serviceName参数,我们可以在构造函数中设置它,其他方法将使用该服务名称。 timeoutMilliseconds 参数。StartOrRestart 和StopServiceIfRunning,可以将其视为其他基本方法的包装器,这些方法的目的只是为了避免异常,如注释中所述。这是课程
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 添加到您的项目中以使其正常工作。
【讨论】:
看到这个article。
这是来自article 的sn-p。
//[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);
我在我的服务中做了同样的事情。它工作正常。
【讨论】: