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
How can I restart a windows service programmatically in .NET
提问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.
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 WaitForStatus
method of the ServiceController
.
执行服务重启时需要做的操作,我猜你应该自己在Service里面做(如果是你自己的服务)。
如果您没有访问该服务的来源,那么也许你可以使用WaitForStatus
的方法ServiceController
。
回答by Donut
This articleuses the ServiceController
class 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 net
command 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.Exit
with 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(这个问题中投票最多的答案),但做了一些修改。
- Disposing of
ServiceController
class after each use, because it implementsIDisposable
interface. - Reduce the parameters of the method: there is no need to the
serviceName
parameter 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. - Handle the catch exception in a way that this class could be used as a component.
- Remove the
timeoutMilliseconds
parameter from each method. - Add two new methods
StartOrRestart
andStopServiceIfRunning
, 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.
ServiceController
每次使用后处理类,因为它实现了IDisposable
接口。- 减少方法的参数:不需要
serviceName
为每个方法传递参数,我们可以在构造函数中设置它,每个其他方法都会使用该服务名称。
这也更加 OOP 友好。 - 以此类可用作组件的方式处理 catch 异常。
timeoutMilliseconds
从每个方法中删除参数。- 添加两个新方法
StartOrRestart
andStopServiceIfRunning
,它们可以被认为是其他基本方法的包装器,这些方法的目的只是为了避免异常,如注释中所述。
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.
请务必使用重置失败计数属性来防止服务完全停止。