如何检查Windows服务是否已在C#中安装


79

我编写了Windows服务,将WCF服务公开给安装在同一台计算机上的GUI。在运行GUI时,如果无法连接到服务,则需要知道是由于尚未安装服务应用程序还是因为服务未运行。如果是前者,我将要安装它(如描述这里); 如果是后者,我将要启动它。

问题是:如何检测是否已安装该服务,然后检测到已安装该服务,如何启动它?

Answers:


147

采用:

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

谢谢-正是我所需要的!
Shaul Behr 2010年

1
使用(var sc = ServiceController.GetServices()。FirstOrDefault(s => s.ServiceName ==“ myservice”))-我认为这是一种更好的方法。
Alexandru Dicu

4
@alexandrudicu:哪种方法更好?如果.GetServices()返回100个ServiceController对象,而您却忽略了其余的一百个对象,那真的好得多吗?我自己不会这么说。
2013年

37

您也可以使用以下内容:

using System.ServiceProcess; 
... 
var serviceExists = ServiceController.GetServices().Any(s => s.ServiceName == serviceName);

3
IMO,这是检查您的服务是否存在的最优雅的方法。利用Linq的强大功能,只需一行代码。顺便说一句,.Any()返回一个布尔值,当您问是/否问题时,它正是您想要的布尔值:-)
Alex X.

3
如果您需要检查远程计算机上的服务,请使用GetServices(string)
ShooShoSha

7

实际上像这样循环:

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

谢谢!并且您想完成以下内容:最后{SC.Close(); }
Cel 2014年

6
为什么不包装整个东西呢?由于using语句将自动进行处理,因此将不需要final {SC.Close()}。using(ServiceController SC = new ServiceController(“ MyServiceName”))
法案

2

对于非linq,您可以像这样遍历数组:

using System.ServiceProcess;

bool serviceExists = false
foreach (ServiceController sc in ServiceController.GetServices())
{
    if (sc.ServiceName == "myServiceName")
    {
         //service is found
         serviceExists = true;
         break;
    }
}

1

我认为这是此问题的最佳答案。无需添加额外的处理来验证服务是否存在,因为如果服务不存在,它将引发异常。您只需要抓住它。如果将整个方法包装在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       
 }     
}

2
根本不是一个很好的答案。(1)通过异常管理代码是非常糟糕的做法-低效且缓慢,并且(2)公认的答案简洁,简洁并且可以完美地满足要求。在深入探讨自己的答案之前,您是否看过它?
Shaul Behr 2014年

显然,您不知道如何像接受的答案那样阅读,因为他清楚地也询问了如何启动该服务,该服务未包含在原始答案中。
法案

显然,您不知道如何正确编写代码。正如@Shaul Behr所说的那样,您的方法是无效的做法,因为它效率低下且速度慢。陈述自己的答案可能是最好的,甚至更糟:在SO上(也可能在世界范围内),自夸从未被视为一种好行为。
Yoda's

1
显然,我不知道有什么更糟的。。。您无法使用正确的语法来尝试看起来自己在说什么,或者您无法意识到自己只是在2014年的一个话题上发表了评论。
法案

这是唯一的答案,说明了如果有人在检查服务存在与与之交互之间删除服务,将会发生什么情况
Mike Caron

1
 private bool ServiceExists(string serviceName)
    {
        ServiceController[] services = ServiceController.GetServices();
        var service = services.FirstOrDefault(s => string.Equals(s.ServiceName, serviceName, StringComparison.OrdinalIgnoreCase));
        return service != null;
    }
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.