Як перевірити, чи встановлена ​​служба Windows у C #


79

Я написав службу Windows, яка надає службу WCF графічному інтерфейсу користувача, встановленому на тій самій машині. Коли я запускаю графічний інтерфейс, якщо я не можу підключитися до служби, мені потрібно знати, чи це тому, що додаток служби ще не встановлений, чи тому, що служба не запущена. Якщо перший, я захочу встановити його (як описано тут ); якщо остання, я хочу запустити її.

Запитання: як визначити, чи встановлена ​​послуга, а потім, виявивши, що вона встановлена, як її запустити?

Відповіді:


147

Використання:

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

Дякую - саме те, що мені було потрібно!
Shaul Behr

1
за допомогою (var sc = ServiceController.GetServices (). FirstOrDefault (s => s.ServiceName == "myservice")) - Я думаю, що це кращий підхід.
Александру Діку

4
@alexandrudicu: Як це кращий підхід? Якщо .GetServices()повертає 100 ServiceControllerоб’єктів, і ви утилізували один із сотні, ігноруючи решту, це дійсно помітно краще? Сам би не сказав.
Аллон Гуралнек,

37

Ви також можете скористатися наступним.

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

3
IMO, це найелегантніший спосіб перевірити, чи існує ваша послуга. Лише один рядок коду, використовуючи потужність Linq. І до речі, .Any () повертає bool, який є саме тим, що ви хочете, задаючи запитання так / ні :-)
Alex X.

3
Якщо вам потрібно перевірити послуги на віддаленій машині, скористайтесяGetServices(string)
ShooShoSha

7

Насправді цикл такий:

foreach (ServiceController SC in ServiceController.GetServices())

може викинути виняток "Відмовлено в доступі", якщо обліковий запис, під яким працює ваша програма, не має прав на перегляд властивостей служби. З іншого боку, ви можете сміливо робити це, навіть якщо жодна послуга з такою назвою не існує:

ServiceController SC = new ServiceController("AnyServiceName");

Але доступ до його властивостей, якщо служба не існує, призведе до InvalidOperationException. Отже, ось безпечний спосіб перевірити, чи встановлена ​​послуга:

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

Дякую! і чи хотіли б ви закінчити з: нарешті {SC.Close (); }
Чел

6
Чому б не обернути всю річ у використанні? Це позбавить вас від необхідності нарешті {SC.Close ()}, оскільки оператор using автоматично розпоряджається. за допомогою (ServiceController SC = new ServiceController ("MyServiceName"))
рахунок

2

Для non-linq ви можете просто перебирати масив так:

using System.ServiceProcess;

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

1

Я думаю, що це найкраща відповідь на це питання. Немає необхідності додавати додаткову обробку, щоб перевірити, чи існує служба, оскільки вона видасть виняток, якщо її немає. Вам просто потрібно зловити його. Вам також не потрібно закривати () з'єднання, якщо обернути весь метод у використанні ().

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
Не дуже хороша відповідь взагалі. (1) Управління кодом за винятками є дуже поганою практикою - неефективне та повільне, і (2) прийнята відповідь акуратна, стисла та ідеально відповідає вимогам. Ви дивились на це перед тим, як зануритися з власною відповіддю?
Шауль Бер

Очевидно, ви не вмієте читати, як прийнята відповідь, оскільки він чітко запитав, як запустити послугу, яка не була включена в оригінальну відповідь.
рахунок

Мабуть, ви не знаєте, як правильно писати код. Як уже зазначав @Shaul Behr, ваш підхід є поганою практикою, оскільки він неефективний і повільний. Зазначення власної відповіді, мабуть, найкраще, ще гірше: самопохвала ніколи не вважається хорошою поведінкою тут, на SO (і, мабуть, також у всьому світі).
Йода

1
Мабуть, я не знаю, що гірше ... Ваша нездатність використовувати належну граматику у вашій спробі виглядати так, ніби ви знаєте, що ви говорите, або ваша нездатність зрозуміти, що ви щойно прокоментували тему з 2014 року .... Лол.
вексель

Це єдина відповідь, яка пояснює, що відбувається, якщо хтось видаляє послугу між перевіркою її існування та взаємодією з нею
Майк Карон

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;
    }
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.