2010-12-29 31 views
64

Ho scritto un servizio Windows che espone un servizio WCF a una GUI installata sulla stessa macchina. Quando eseguo la GUI, se non riesco a connettermi al servizio, ho bisogno di sapere se è perché l'app di servizio non è ancora stata installata, o se è perché il servizio non è in esecuzione. Se il primo, voglio installarlo (come descritto here); se quest'ultimo, voglio iniziare.Come verificare se è installato un servizio Windows in C#

Domanda: come si rileva se il servizio è installato e dopo aver rilevato che è installato, come si avvia?

risposta

116

Usa:

// 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 Interessante ... –

+0

Grazie - proprio quello che mi serviva! –

+1

+1 brillante! E grazie. –

27

è possibile utilizzare il seguente come pure ..

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

IMO, questo è il modo più elegante per verificare se il servizio esiste. Solo una riga di codice, sfruttando la potenza di Linq. E a proposito,. Any() restituisce un bool che è esattamente quello che vuoi quando fai una domanda si/no :-) –

+0

Se hai bisogno di controllare i servizi su una macchina remota, usa ['GetServices (stringa)'] (https://msdn.microsoft.com/en-us/library/s21fd6th.aspx) – ShooShoSha

2

Per i non-LINQ, si può semplicemente scorrere attraverso l'array come questo:

using System.ServiceProcess; 

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

Effettivamente il looping in questo modo:

foreach (ServiceController SC in ServiceController.GetServices()) 

può generare un'eccezione di accesso negato se l'account con cui è in esecuzione l'applicazione non dispone dei diritti per visualizzare le proprietà del servizio. D'altra parte, si può tranquillamente farlo anche se nessun servizio con tale nome esiste:

ServiceController SC = new ServiceController("AnyServiceName"); 

Ma accedendo alla sua proprietà se il servizio non esiste si tradurrà in InvalidOperationException. Quindi, ecco un modo sicuro per controllare se è installato un servizio:

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

grazie! e si desidera terminare con: infine { SC.Close(); } – Cel

+2

Perché non avvolgere l'intera cosa nell'utilizzo? Ciò eliminerà definitivamente la necessità di {SC.Close()} poiché l'istruzione using verrà automaticamente eliminata. utilizzando (ServiceController SC = nuovo ServiceController ("MyServiceName")) – bill

0

Penso che questa sia la migliore risposta per questa domanda. Non è necessario aggiungere ulteriore elaborazione per verificare se il servizio esiste, dal momento che genererà un'eccezione se non lo fa. Hai solo bisogno di prenderlo. Inoltre non è necessario chiudere() la connessione se si avvolge l'intero metodo in 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  
}  
} 
+0

Non è affatto una buona risposta.(1) Gestire il codice in base alle eccezioni è una pratica molto negativa - inefficiente e lento, e (2) la risposta accettata è chiara, concisa e risponde perfettamente ai requisiti. L'hai guardato prima di immergerti con la tua risposta? –

+0

Apparentemente non sai come leggere come la risposta accettata, dal momento che ha chiesto chiaramente come avviare il servizio, che non è stato incluso nella risposta originale. – bill

+0

Apparentemente, non sai come scrivere correttamente il codice. Come ha già affermato @Shaul Behr, il tuo approccio è una cattiva pratica in quanto è inefficiente e lento. Dire che la tua risposta _own_ è probabilmente la migliore, lo rende ancora peggiore: l'auto-lode non è mai considerato un buon comportamento qui su SO (e probabilmente anche in tutto il mondo). – 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; 
    } 
Problemi correlati