Escribí 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 del servicio aún no se ha instalado o si el servicio no se está ejecutando. Si es el primero, querré instalarlo (como se describe aquí ); si es lo último, querré ponerlo en marcha.
La pregunta es: ¿cómo detecta si el servicio está instalado, y luego de haber detectado que está instalado, cómo lo inicia?
c#
wcf
windows-services
Shaul Behr
fuente
fuente
.GetServices()
devuelve 100ServiceController
objetos y ha eliminado uno de los cien ignorando el resto, ¿es realmente sensiblemente mejor? Yo mismo no diría eso.También podría utilizar lo siguiente ...
using System.ServiceProcess; ... var serviceExists = ServiceController.GetServices().Any(s => s.ServiceName == serviceName);
fuente
GetServices(string)
Realmente haciendo un bucle así:
foreach (ServiceController SC in ServiceController.GetServices())
puede lanzar la excepción Acceso denegado si la cuenta bajo la cual se ejecuta su aplicación no tiene derechos para ver las propiedades del servicio. Por otro lado, puede hacer esto de manera segura incluso si no existe ningún servicio con ese nombre:
ServiceController SC = new ServiceController("AnyServiceName");
Pero acceder a sus propiedades si el servicio no existe resultará en InvalidOperationException. Entonces, aquí hay una forma segura de verificar si un servicio está instalado:
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(); }
fuente
Para no linq, 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; } }
fuente
Creo que esta es la mejor respuesta para esta pregunta. No es necesario agregar procesamiento adicional para verificar si el servicio existe, ya que lanzará una excepción si no lo hace. Solo necesitas atraparlo. Tampoco es necesario cerrar () la conexión si envuelve todo el método en 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 } }
fuente
private bool ServiceExists(string serviceName) { ServiceController[] services = ServiceController.GetServices(); var service = services.FirstOrDefault(s => string.Equals(s.ServiceName, serviceName, StringComparison.OrdinalIgnoreCase)); return service != null; }
fuente