2010-12-29 14 views
64

He escrito un Servicio de Windows que expone un servicio WCF a una GUI instalada en la misma máquina. Cuando ejecuto la GUI, si no puedo conectarme al servicio, necesito saber si es porque la aplicación de servicio aún no se ha instalado o si se debe a que el servicio no se está ejecutando. Si el primero, deseo instalarlo (como se describe en here); si es lo último, querré ponerlo en marcha.Cómo verificar si un servicio de Windows está instalado en C#

La pregunta es: ¿cómo se detecta si el servicio está instalado y luego de detectar que está instalado, cómo se inicia?

Respuesta

116

Uso:

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

+1 Interesante ... –

+0

Gracias - justo lo que necesitaba! –

+1

+1 Brillante! Y gracias. –

27

podría utilizar el siguiente, así ..

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

IMO, esta es la manera más elegante de verificar si su servicio existe. Solo una línea de código, aprovechando el poder de Linq. Y, por cierto, .Any() devuelve un bool que es exactamente lo que quiere cuando hace una pregunta sí/no :-) –

+0

Si necesita verificar servicios en una máquina remota, use ['GetServices (string)'] (https://msdn.microsoft.com/en-us/library/s21fd6th.aspx) – ShooShoSha

2

Para no LINQ, sólo puede iterar a través de la matriz de esta manera:

using System.ServiceProcess; 

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

Actually looping como este:

foreach (ServiceController SC in ServiceController.GetServices()) 

puede lanzar una excepción Acceso denegado si la cuenta bajo la cual se ejecuta la aplicación no tiene derechos para ver las propiedades del servicio. Por otro lado, puede hacerlo con seguridad esto incluso si no existe ningún servicio con tal nombre:

ServiceController SC = new ServiceController("AnyServiceName"); 

Pero el acceso a sus propiedades si el servicio no existe dará lugar a InvalidOperationException. Así que aquí es una manera segura para comprobar si se ha instalado un servicio:

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

¡gracias! y le gustaría terminar con: finalmente { SC.Close(); } – Cel

+2

¿Por qué no envolver todo en el uso? Eso eliminará la necesidad de finalmente {SC.Close()} ya que una sentencia using eliminará automáticamente. usando (ServiceController SC = new ServiceController ("MyServiceName")) – bill

0

Creo que esta es la mejor respuesta para esta pregunta. No es necesario agregar procesamiento adicional para verificar si existe el servicio, ya que arrojará una excepción si no lo hace. Solo necesitas atraparlo. Tampoco necesita cerrar() la conexión si ajusta todo el método al usar().

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  
}  
} 
+0

No es una muy buena respuesta.(1) Administrar el código por excepciones es una práctica muy mala: ineficiente y lento, y (2) la respuesta aceptada es clara, concisa y responde perfectamente a los requisitos. ¿Lo viste antes de sumergirte con tu propia respuesta? –

+0

Aparentemente, usted no sabe leer como la respuesta aceptada, ya que claramente preguntó cómo comenzar el servicio, lo que no estaba incluido en la respuesta original. – bill

+0

Aparentemente, no sabes cómo escribir correctamente el código. Como ya dijo @Shaul Behr, su enfoque es una mala práctica ya que es ineficiente y lento. Declarar su propia respuesta es probablemente la mejor, lo empeora aún más: el autoelogio nunca se considera un buen comportamiento aquí en SO (y probablemente en todo el mundo, también). – Yoda

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; 
    } 
Cuestiones relacionadas