Jak sprawdzić, czy usługa systemu Windows jest zainstalowana w C #


79

Napisałem usługę Windows, która uwidacznia usługę WCF do GUI zainstalowanego na tym samym komputerze. Kiedy uruchamiam GUI, jeśli nie mogę połączyć się z usługą, muszę wiedzieć, czy dzieje się tak dlatego, że aplikacja usługi nie została jeszcze zainstalowana, czy też dlatego, że usługa nie działa. Jeśli pierwszy, będę chciał go zainstalować (jak opisano tutaj ); jeśli to drugie, będę chciał go uruchomić.

Pytanie brzmi: w jaki sposób wykryjesz, czy usługa jest zainstalowana, a następnie po wykryciu, że jest zainstalowana, jak ją uruchomić?

Odpowiedzi:


147

Posługiwać się:

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

Dziękuję - właśnie tego potrzebowałem!
Shaul Behr

1
using (var sc = ServiceController.GetServices (). FirstOrDefault (s => s.ServiceName == "myservice")) - myślę, że jest to lepsze podejście.
Alexandru Dicu,

4
@alexandrudicu: Jakie jest lepsze podejście? Jeśli .GetServices()zwróci 100 ServiceControllerobiektów i pozbyłeś się jednego na sto, ignorując resztę, czy to naprawdę znacznie lepsze? Sam bym tego nie powiedział.
Allon Guralnek

37

Możesz również użyć następujących.

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

3
IMO, to najbardziej elegancki sposób sprawdzenia, czy Twoja usługa istnieje. Tylko jedna linia kodu, wykorzystująca moc Linq. Nawiasem mówiąc, .Any () zwraca wartość bool, która jest dokładnie tym, czego oczekujesz, zadając pytanie tak / nie :-)
Alex X.

3
Jeśli chcesz sprawdzić usługi na zdalnym komputerze, użyjGetServices(string)
ShooShoSha

7

Właściwie zapętlony w ten sposób:

foreach (ServiceController SC in ServiceController.GetServices())

może zgłosić wyjątek Odmowa dostępu, jeśli konto, na którym działa aplikacja, nie ma uprawnień do wyświetlania właściwości usługi. Z drugiej strony możesz to bezpiecznie zrobić, nawet jeśli nie istnieje usługa o takiej nazwie:

ServiceController SC = new ServiceController("AnyServiceName");

Ale dostęp do jego właściwości, jeśli usługa nie istnieje, spowoduje InvalidOperationException. Oto bezpieczny sposób sprawdzenia, czy usługa jest zainstalowana:

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

dzięki! i czy chciałbyś zakończyć: w końcu {SC.Close (); }
Cel,

6
Dlaczego nie zawinąć całej rzeczy w użycie? To wyeliminuje ostatecznie potrzebę {SC.Close ()}, ponieważ instrukcja using zostanie automatycznie usunięta. using (ServiceController SC = new ServiceController ("MyServiceName"))
rachunek

2

Dla non-linq możesz po prostu iterować przez tablicę w następujący sposób:

using System.ServiceProcess;

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

1

Myślę, że to najlepsza odpowiedź na to pytanie. Nie ma potrzeby dodawania dodatkowego przetwarzania, aby sprawdzić, czy usługa istnieje, ponieważ zgłosi wyjątek, jeśli tak nie jest. Po prostu musisz to złapać. Nie musisz również zamykać () łączenia, jeśli zawiniesz całą metodę za pomocą ().

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
Niezbyt dobra odpowiedź. (1) Zarządzanie kodem za pomocą wyjątków jest bardzo złą praktyką - nieefektywną i powolną, oraz (2) przyjęta odpowiedź jest zgrabna, zwięzła i doskonale spełnia wymagania. Czy spojrzałeś na to, zanim zagłębiłeś się w swoją własną odpowiedź?
Shaul Behr

Najwyraźniej nie wiesz, jak czytać, jak zaakceptowana odpowiedź, ponieważ wyraźnie zapytał, jak również uruchomić usługę, czego nie było w pierwotnej odpowiedzi.
rachunek z

Najwyraźniej nie wiesz, jak poprawnie pisać kod. Jak już powiedział @Shaul Behr, twoje podejście jest złą praktyką, ponieważ jest nieefektywne i powolne. Podanie własnej odpowiedzi jest prawdopodobnie najlepsze, a to jeszcze gorsze: chwalenie siebie nigdy nie jest uważane za dobre zachowanie tutaj na SO (i prawdopodobnie na całym świecie).
Yoda

1
Najwyraźniej nie wiem, co jest gorsze ... Twoja niezdolność do użycia prawidłowej gramatyki, aby wyglądać, jakbyś wiedział, co mówisz, lub niezdolność do zrozumienia, że ​​właśnie skomentowałeś wątek z 2014 roku ... Lol.
rachunek

To jedyna odpowiedź, która wyjaśnia, co się stanie, jeśli ktoś usunie usługę między sprawdzeniem jej istnienia a interakcją z nią
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;
    }
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.