So überprüfen Sie, ob ein Windows-Dienst in C # installiert ist

79

Ich habe einen Windows-Dienst geschrieben, der einen WCF-Dienst einer auf demselben Computer installierten GUI zur Verfügung stellt. Wenn ich die GUI ausführe und keine Verbindung zum Dienst herstellen kann, muss ich wissen, ob die Dienst-App noch nicht installiert wurde oder ob der Dienst nicht ausgeführt wird. Wenn erstere, möchte ich es installieren (wie hier beschrieben ); Wenn letzteres der Fall ist, möchte ich es starten.

Die Frage ist: Wie erkennen Sie, ob der Dienst installiert ist, und wie starten Sie ihn, nachdem Sie festgestellt haben, dass er installiert ist?

Shaul Behr
quelle

Antworten:

146

Verwenden:

// 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);
Aliostad
quelle
Danke - genau das, was ich brauchte!
Shaul Behr
1
using (var sc = ServiceController.GetServices (). FirstOrDefault (s => s.ServiceName == "myservice")) - Ich denke, dies ist ein besserer Ansatz.
Alexandru Dicu
4
@alexandrudicu: Wie ist das ein besserer Ansatz? Wenn .GetServices()100 ServiceControllerObjekte zurückgegeben werden und Sie eines von hundert Objekten entsorgt haben, während Sie den Rest ignoriert haben, ist das wirklich spürbar besser? Das würde ich selbst nicht sagen.
Allon Guralnek
37

Sie können auch Folgendes verwenden:

using System.ServiceProcess; 
... 
var serviceExists = ServiceController.GetServices().Any(s => s.ServiceName == serviceName);
Simon Oliver Hurley
quelle
3
IMO, dies ist die eleganteste Methode, um zu überprüfen, ob Ihr Service vorhanden ist. Nur eine Codezeile, die die Leistung von Linq nutzt. Übrigens, .Any () gibt einen Bool zurück, der genau das ist, was Sie wollen, wenn Sie eine Ja / Nein-Frage stellen :-)
Alex X.
3
Wenn Sie Dienste auf einem Remote-Computer überprüfen müssen, verwenden SieGetServices(string)
ShooShoSha
7

Eigentlich Schleife wie folgt:

foreach (ServiceController SC in ServiceController.GetServices())

kann die Ausnahme "Zugriff verweigert" auslösen, wenn das Konto, unter dem Ihre Anwendung ausgeführt wird, nicht zum Anzeigen von Diensteigenschaften berechtigt ist. Auf der anderen Seite können Sie dies sicher tun, auch wenn kein Dienst mit einem solchen Namen vorhanden ist:

ServiceController SC = new ServiceController("AnyServiceName");

Der Zugriff auf seine Eigenschaften, wenn kein Dienst vorhanden ist, führt jedoch zu InvalidOperationException. Hier ist eine sichere Methode, um zu überprüfen, ob ein Dienst installiert ist:

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();
}
ttaaoossuu
quelle
Vielen Dank! und möchten Sie beenden mit: finally {SC.Close (); }
Cel
6
Warum nicht das Ganze einpacken? Dadurch wird die Notwendigkeit von final {SC.Close ()} beseitigt, da eine using-Anweisung automatisch entsorgt wird. using (ServiceController SC = neuer ServiceController ("MyServiceName"))
Rechnung
2

Für Nicht-Linq können Sie das Array einfach wie folgt durchlaufen:

using System.ServiceProcess;

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

Ich denke, das ist die beste Antwort auf diese Frage. Es ist nicht erforderlich, zusätzliche Verarbeitung hinzuzufügen, um zu überprüfen, ob der Dienst vorhanden ist, da sonst eine Ausnahme ausgelöst wird. Sie müssen es nur fangen. Sie müssen die Verbindung auch nicht schließen (), wenn Sie die gesamte Methode mit using () umschließen.

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       
 }     
}
Rechnung
quelle
2
Überhaupt keine sehr gute Antwort. (1) Das Verwalten von Code durch Ausnahmen ist eine sehr schlechte Praxis - ineffizient und langsam, und (2) die akzeptierte Antwort ist ordentlich, präzise und entspricht den Anforderungen perfekt. Hast du es dir angesehen, bevor du mit deiner eigenen Antwort eingetaucht bist?
Shaul Behr
Anscheinend wissen Sie nicht, wie man wie die akzeptierte Antwort liest, da er eindeutig gefragt hat, wie der Dienst ebenfalls gestartet werden soll, was in der ursprünglichen Antwort nicht enthalten war.
Rechnung
Anscheinend wissen Sie nicht, wie man Code richtig schreibt. Wie @Shaul Behr bereits sagte, ist Ihr Ansatz eine schlechte Praxis, da er ineffizient und langsam ist. Die Angabe Ihrer eigenen Antwort ist wahrscheinlich die beste und macht sie noch schlimmer: Selbstlob wird hier auf SO (und wahrscheinlich auch auf der ganzen Welt) nie als gutes Verhalten angesehen.
Yoda
1
Anscheinend weiß ich nicht, was schlimmer ist ... Ihre Unfähigkeit, die richtige Grammatik zu verwenden, um so auszusehen, als ob Sie wissen, was Sie sagen, oder Ihre Unfähigkeit zu erkennen, dass Sie gerade einen Thread aus dem Jahr 2014 kommentiert haben ... Lol.
Rechnung
Dies ist die einzige Antwort, die erklärt, was passiert, wenn jemand den Dienst zwischen der Überprüfung seiner Existenz und der Interaktion mit ihm löscht
Mike Caron
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;
    }
Ajaya Nayak
quelle