我编写了Windows服务,将WCF服务公开给安装在同一台计算机上的GUI。在运行GUI时,如果无法连接到服务,则需要知道是由于尚未安装服务应用程序还是因为服务未运行。如果是前者,我将要安装它(如描述这里); 如果是后者,我将要启动它。
问题是:如何检测是否已安装该服务,然后检测到已安装该服务,如何启动它?
Answers:
采用:
// add a reference to System.ServiceProcess.dll
using System.ServiceProcess;
// ...
ServiceController ctl = ServiceController.GetServices()
.FirstOrDefault(s => s.ServiceName == "myservice");
if(ctl==null)
Console.WriteLine("Not installed");
else
Console.WriteLine(ctl.Status);
.GetServices()
返回100个ServiceController
对象,而您却忽略了其余的一百个对象,那真的好得多吗?我自己不会这么说。
您也可以使用以下内容:
using System.ServiceProcess;
...
var serviceExists = ServiceController.GetServices().Any(s => s.ServiceName == serviceName);
GetServices(string)
实际上像这样循环:
foreach (ServiceController SC in ServiceController.GetServices())
如果运行您的应用程序所在的帐户没有查看服务属性的权限,则可能会抛出“拒绝访问”异常。另一方面,即使不存在具有该名称的服务,也可以安全地执行此操作:
ServiceController SC = new ServiceController("AnyServiceName");
但是,如果不存在服务,则访问其属性将导致InvalidOperationException。因此,这是检查服务是否已安装的安全方法:
ServiceController SC = new ServiceController("MyServiceName");
bool ServiceIsInstalled = false;
try
{
// actually we need to try access ANY of service properties
// at least once to trigger an exception
// not neccessarily its name
string ServiceName = SC.DisplayName;
ServiceIsInstalled = true;
}
catch (InvalidOperationException) { }
finally
{
SC.Close();
}
我认为这是此问题的最佳答案。无需添加额外的处理来验证服务是否存在,因为如果服务不存在,它将引发异常。您只需要抓住它。如果将整个方法包装在using()中,则也不需要关闭连接。
using (ServiceController sc = new ServiceController(ServiceName))
{
try
{
if (sc.Status != ServiceControllerStatus.Running)
{
sc.Start();
sc.WaitForStatus(ServiceControllerStatus.Running, new TimeSpan(0, 0, 10));
//service is now Started
}
else
//Service was already started
}
catch (System.ServiceProcess.TimeoutException)
{
//Service was stopped but could not restart (10 second timeout)
}
catch (InvalidOperationException)
{
//This Service does not exist
}
}
private bool ServiceExists(string serviceName)
{
ServiceController[] services = ServiceController.GetServices();
var service = services.FirstOrDefault(s => string.Equals(s.ServiceName, serviceName, StringComparison.OrdinalIgnoreCase));
return service != null;
}