如何检查是不是在 C# 中安装了 Windows 服务

Posted

技术标签:

【中文标题】如何检查是不是在 C# 中安装了 Windows 服务【英文标题】:How to check if a windows service is installed in C#如何检查是否在 C# 中安装了 Windows 服务 【发布时间】:2011-06-01 01:06:39 【问题描述】:

我编写了一个 Windows 服务,它将 WCF 服务公开给安装在同一台机器上的 GUI。当我运行 GUI 时,如果我无法连接到服务,我需要知道是因为尚未安装服务应用程序,还是因为服务没有运行。如果是前者,我想安装它(如here 所述);如果是后者,我会想启动它。

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

【问题讨论】:

【参考方案1】:

用途:

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

【讨论】:

谢谢你——正是我需要的! using (var sc = ServiceController.GetServices().FirstOrDefault(s => s.ServiceName == "myservice")) - 我认为这是一个更好的方法。 @alexandrudicu:这是一种更好的方法吗?如果 .GetServices() 返回 100 个 ServiceController 对象,而您已经处理了 100 个对象中的一个,而忽略了其余对象,那真的会更好吗?我自己不会这么说。【参考方案2】:

您也可以使用以下内容..

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

【讨论】:

IMO,这是检查您的服务是否存在的最优雅的方法。只需一行代码,即可利用 Linq 的强大功能。顺便说一句,.Any() 返回一个布尔值,这正是你在问是/否问题时想要的:-) 如果需要检查远程机器上的服务,请使用GetServices(string)【参考方案3】:

其实是这样循环的:

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

【讨论】:

谢谢!你想结束:finally SC.Close(); 为什么不把整个东西包起来使用呢?这将消除对 finallySC.Close() 的需要,因为 using 语句将自动处理。 using(ServiceController SC = new ServiceController("MyServiceName"))【参考方案4】:

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

using System.ServiceProcess;

bool serviceExists = false
foreach (ServiceController sc in ServiceController.GetServices())

    if (sc.ServiceName == "myServiceName")
    
         //service is found
         serviceExists = true;
         break;
    

【讨论】:

【参考方案5】:

我认为这是这个问题的最佳答案。无需添加额外的处理来验证服务是否存在,因为如果不存在则会抛出异常。你只需要抓住它。如果将整个方法包装在 using() 中,也不需要 close() 连接。

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       
      

【讨论】:

根本不是一个很好的答案。 (1) 通过异常管理代码是一种非常糟糕的做法 - 效率低下且速度慢,并且 (2) 接受的答案简洁明了,并且完美地满足了要求。在提出自己的答案之前,您是否看过它? 显然你不知道如何像接受的答案那样阅读,因为他也清楚地询问了如何启动服务,而这并没有包含在原始答案中。 显然,您不知道如何正确编写代码。正如@Shaul Behr 已经说过的那样,您的方法是不好的做法,因为它效率低下且速度慢。说出你的自己的答案可能是最好的,但会让情况变得更糟:自我表扬在这里从来不被认为是一种好的行为(也许在全世界也是如此)。 显然我不知道更糟糕的是什么......你无法使用正确的语法来试图看起来你知道你在说什么,或者你无法意识到你只是在一个线程上发表评论从 2014 年开始......大声笑。 这是唯一解释如果有人在检查服务存在和与之交互之间删除服务会发生什么情况的唯一答案【参考方案6】:
 private bool ServiceExists(string serviceName)
    
        ServiceController[] services = ServiceController.GetServices();
        var service = services.FirstOrDefault(s => string.Equals(s.ServiceName, serviceName, StringComparison.OrdinalIgnoreCase));
        return service != null;
    

【讨论】:

以上是关于如何检查是不是在 C# 中安装了 Windows 服务的主要内容,如果未能解决你的问题,请参考以下文章

如果在 Internet Explorer 中安装了 Lync 插件,我如何检查 Javascript?

Android:如何知道是不是已经使用 adb 在 android 设备中安装了任何应用程序?

如何判断 Linux 机器上的目录是不是在 Java 中安装了外部文件系统?

如何从文本框(windows窗体)检查主键是不是存在于我的数据库中,c#

从浏览器检测是不是在 Android 中安装了特定应用程序

Windows10 Docker安装详细教程