2010-10-20 37 views
39

不知道是否有更好的方法來做到這一點,所以這就是問題的原因。我可以檢查是否有特定的計算機上是否存在服務用下面的代碼:檢查特定機器上是否存在服務而不使用異常處理

bool DoesServiceExist(string serviceName, string machineName) 
{ 
    ServiceController controller = null; 
    try 
    { 
     controller = new ServiceController(serviceName, machineName); 
     controller.Status; 
     return true; 
    } 
    catch(InvalidOperationException) 
    { 
     return false; 
    } 
    finally 
    { 
     if (controller != null) 
     { 
      controller.Dispose(); 
     } 
    } 
} 

但是這似乎是一個ineffecient解決方案,我(由於異常處理)。有沒有更好的方法來檢查服務是否存在。注意 - 我最近轉向.Net 4.0,所以如果有人知道4.0中更好的解決方案是可以接受的。

編輯: 下面是一個示例c#控制檯應用程序來測試我的示例以及GetServices代碼示例的性能。在我的測試中,我發現GetServices遠在服務中不存在的情況下更多的表演,但是當服務確實存在是慢一倍:

static void Main(string[] args) 
    { 
     string serviceName = string.Empty; 
     string machineName = string.Empty; 

     var sw = new Stopwatch(); 
     sw.Reset(); 
     sw.Start(); 
     for (int i = 0; i < 1000; i++) 
     { 
      ServiceExistsException(serviceName, machineName); 
     } 
     sw.Stop(); 
     Console.WriteLine("Elapsed time: " + sw.ElapsedMilliseconds.ToString()); 
     sw.Reset(); 
     sw.Start(); 
     for (int i = 0; i < 1000; i++) 
     { 
      ServiceExistsGetList(serviceName, machineName); 
     } 
     sw.Stop(); 
     Console.WriteLine("Elapsed time: " + sw.ElapsedMilliseconds.ToString()); 

     Console.WriteLine("Done"); 
     Console.ReadLine(); 
    } 

    static bool ServiceExistsException(string serviceName, string machineName) 
    { 
     ServiceController controller = null; 
     try 
     { 
      controller = new ServiceController(serviceName, machineName); 
      string name = controller.DisplayName; 
      return true; 
     } 
     catch (InvalidOperationException) 
     { 
      return false; 
     } 
     finally 
     { 
      if (controller != null) 
      { 
       controller.Dispose(); 
      } 
     } 
    } 

    static bool ServiceExistsGetList(string serviceName, string machineName) 
    { 
     ServiceController[] services = null; 
     try 
     { 
      services = ServiceController.GetServices(machineName); 
      var service = services.FirstOrDefault(s => s.ServiceName == serviceName); 
      return service != null; 
     } 
     finally 
     { 
      if (services != null) 
      { 
       foreach (ServiceController controller in services) 
       { 
        controller.Dispose(); 
       } 
      } 
     } 
    } 
} 

回答

67

可以使用ServiceController.GetServices()方法來獲取所有的機器上的服務,然後通過他們看,看看是否存在一個名爲你在找什麼:

bool DoesServiceExist(string serviceName, string machineName) 
{ 
    ServiceController[] services = ServiceController.GetServices(machineName); 
    var service = services.FirstOrDefault(s => s.ServiceName == serviceName); 
    return service != null; 
} 

FirstOrDefault()擴展方法(從System.Linq)將返回給定名稱的第一個服務,或者如果沒有匹配,則爲null


爲了解決你的速度問題:

的一個方法調用的兩種方法之間的差異可以忽略不計,無論服務是否找到或沒有。這隻會是一個問題,如果你打電話這種方法數千次—在這種情況下獲得服務列表一次,並記住它。

+0

我對你的解決方案的性能有疑問,所以我跑了一個測試。當服務不存在時,您的解決方案具有更高的性能(即使添加了處理服務控制器的代碼)。在服務確實存在的情況下,這種解決方案速度要慢一倍。我不知道現在該做什麼。在我的情況下,我期望更多的時候不會有服務存在。在這種情況下,我的解決方案勝出,在更通用的情況下,您的解決方案勝出。 – pstrjds 2010-10-20 18:54:18

+0

一個額外的評論。基本上這個解決方案在恆定的時間運行,無論服務是否存在。一個好的通用案例解決方案的榮譽。 – pstrjds 2010-10-20 19:15:06

+0

針對速度問題,當服務確實存在時,我在問題中提出的代碼更快(儘管我同意它可以忽略不計)。我通常不會在循環中調用它(只是做了性能分析),否則我可以緩存這個列表。我認爲這個命中是在兩次迭代列表中。一旦找到服務(雖然不一定是整個列表的完整迭代),而另一次要處理這些對象。在我正在執行的情況下,我無法緩存列表,我可能會運行幾天的功能,在這種情況下,服務可能已被刪除。 – pstrjds 2010-10-20 19:52:42

12

與adrianbanks的方法相同,但代碼稍微簡潔。 如果你使用LINQ,你可以使用任何語句來返回你想要的。 另外,如果您正在本地計算機上檢查,則無需提供計算機名稱。

bool DoesServiceExist(string serviceName) 
{ 
    return ServiceController.GetServices().Any(serviceController => serviceController.ServiceName.Equals(serviceName)); 
} 
4

建立在邁克的答案之上。與Dictionary.TryGetValue相同的概念。

/// <summary> 
    /// Gets a <see cref="ServiceController"/> given the specified <see cref="pServiceName"/>. 
    /// </summary> 
    /// <param name="pServiceName">The name of the service.</param> 
    /// <param name="pService">The <see cref="ServiceController"/> associated with the name.</param> 
    /// <returns> 
    /// <see cref="bool.True"/> if the <see cref="ServiceController"/> exists; otherwise <see cref="bool.False"/>. 
    /// </returns> 
    private static bool TryGetService(string pServiceName, out ServiceController pService) 
    { 
     pService = ServiceController.GetServices() 
      .FirstOrDefault(serviceController => serviceController.ServiceName == pServiceName); 

     return pService != null; 
    } 
相關問題