Как проверить, установлена ​​ли служба 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);

Спасибо - именно то, что мне было нужно!
Шауль Бер

1
using (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
ИМО, это самый элегантный способ проверить, существует ли ваша служба. Всего одна строчка кода, раскрывающая всю мощь Linq. И, кстати, .Any () возвращает логическое значение, которое именно то, что вы хотите, задавая вопрос типа да / нет :-)
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();
}

благодаря! и хотели бы вы закончить: finally {SC.Close (); }
Cel

6
Почему бы не обернуть все это в использование? Это устранит необходимость в finally {SC.Close ()}, поскольку оператор using автоматически удаляется. using (ServiceController SC = new ServiceController ("MyServiceName"))
счет

2

Для не-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 ().

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

По-видимому, вы не знаете, как читать принятый ответ, поскольку он также четко спросил, как запустить службу, что не было включено в исходный ответ.
счет

Видимо, вы не умеете правильно писать код. Как уже заявил @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.