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?

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

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

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

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

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

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;
    }
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.