2010-10-20 7 views
39

No sé si hay una mejor manera de hacerlo, por lo que ese es el motivo de la pregunta. Puedo comprobar si existe un servicio en una máquina en particular con el siguiente código:Compruebe si existe un servicio en una máquina en particular sin usar el manejo de excepciones

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

pero esto parece una solución ineficiente para mí (debido al manejo de excepciones). ¿Hay una mejor manera de verificar si existe un servicio? Nota: Recientemente cambié a .Net 4.0, por lo que si alguien sabe de una solución mejor en 4.0 sería aceptable.

EDIT: Aquí hay una aplicación de consola C# para probar el rendimiento de mi ejemplo, así como el ejemplo del código GetServices. En mis pruebas encontré que los GetServices es mucho más performativo en el caso en que no existe el servicio, pero es dos veces más lento cuando el servicio no existe:

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

Respuesta

67

Usted puede utilizar el método ServiceController.GetServices() para obtener todos los servicios en el equipo, a continuación, mirar a través de ellos para ver si existe nombrado lo que busca:

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

el método FirstOrDefault() extensión (de System.Linq) devolverá o bien el primer servicio con el nombre dado o de una null si no hay coincidencia.


Para hacer frente a su problema de velocidad:

La diferencia entre los dos enfoques para una sola llamada al método es despreciable, independientemente de si el servicio se encuentra o no. Solo será un problema si llama a este método miles de veces — en cuyo caso obtenga la lista de servicios una vez y recuérdelo.

+0

Me resultó cuestionable el rendimiento de su solución, por lo que realicé una prueba. Su solución es mucho más performativa (incluso con el código agregado para eliminar los controladores de servicio) cuando el servicio no existe. En el caso donde el servicio existe, esta solución es dos veces más lenta. No estoy seguro de qué hacer ahora. En mi caso, espero que la mayoría de las veces el servicio exista. En ese caso, mi solución gana, en el caso más genérico, su solución gana. – pstrjds

+0

Un comentario adicional. Básicamente, esta solución se ejecuta en tiempo constante, ya sea que el servicio exista o no. Felicitaciones por una buena solución de caso genérico. – pstrjds

+0

En respuesta al problema de velocidad, el código que presenté en la pregunta es más rápido cuando el servicio existe (aunque estoy de acuerdo en que es insignificante). Normalmente no estaría llamando esto en un bucle (simplemente lo hice para el análisis de rendimiento), de lo contrario podría almacenar en caché la lista. Creo que el éxito está en iterar la lista dos veces. Una vez para encontrar el servicio (aunque no necesariamente una iteración completa de toda la lista) y otro momento para deshacerse de los objetos. En el caso en que estoy implementando, no puedo almacenar en caché la lista, puedo ejecutar la función con días de diferencia, en cuyo caso el servicio podría haberse eliminado. – pstrjds

12

El mismo enfoque que adrianbanks pero un código un poco más compacto. Si está utilizando LINQ puede usar cualquier declaración para devolver lo que desea. Además, si está revisando una computadora local, no es necesario dar el nombre de la computadora.

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

Construido sobre la respuesta de Mike. Mismo concepto que 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; 
    } 
Cuestiones relacionadas