Проверьте, существует ли служба на определенном компьютере, не используя обработку исключений - PullRequest
46 голосов
/ 20 октября 2010

Не знаю, есть ли лучший способ сделать это, так что это причина вопроса.Я могу проверить, существует ли служба на конкретной машине со следующим кодом:

bool DoesServiceExist(string serviceName, string machineName)
{
    ServiceController controller = null;
    try
    {
        controller = new ServiceController(serviceName, machineName);
        controller.Status;
        return true;
    }
    catch(InvalidOperationException)
    {
        return false;
    }
    finally
    {
         if (controller != null)
         {
             controller.Dispose();
         }
    }
}

, но это кажется мне неэффективным решением (из-за обработки исключений).Есть ли лучший способ проверить, существует ли услуга.Примечание. Недавно я перешел на .Net 4.0, поэтому, если кто-то знает, что в 4.0 лучше решение, которое было бы приемлемым.

РЕДАКТИРОВАТЬ: Вот пример консольного приложения на c # для проверки производительности моего примерапример кода GetServices.В моем тестировании я обнаружил, что GetServices гораздо эффективнее в случае, когда сервис не существует, но в два раза медленнее, когда сервис существует:

    static void Main(string[] args)
    {
        string serviceName = string.Empty;
        string machineName = string.Empty;

        var sw = new Stopwatch();
        sw.Reset();
        sw.Start();
        for (int i = 0; i < 1000; i++)
        {
            ServiceExistsException(serviceName, machineName);
        }
        sw.Stop();
        Console.WriteLine("Elapsed time: " + sw.ElapsedMilliseconds.ToString());
        sw.Reset();
        sw.Start();
        for (int i = 0; i < 1000; i++)
        {
            ServiceExistsGetList(serviceName, machineName);
        }
        sw.Stop();
        Console.WriteLine("Elapsed time: " + sw.ElapsedMilliseconds.ToString());

        Console.WriteLine("Done");
        Console.ReadLine();
    }

    static bool ServiceExistsException(string serviceName, string machineName)
    {
        ServiceController controller = null;
        try
        {
            controller = new ServiceController(serviceName, machineName);
            string name = controller.DisplayName;
            return true;
        }
        catch (InvalidOperationException)
        {
            return false;
        }
        finally
        {
            if (controller != null)
            {
                controller.Dispose();
            }
        }
    }

    static bool ServiceExistsGetList(string serviceName, string machineName)
    {
        ServiceController[] services = null;
        try
        {
            services = ServiceController.GetServices(machineName);
            var service = services.FirstOrDefault(s => s.ServiceName == serviceName);
            return service != null;
        }
        finally
        {
            if (services != null)
            {
                foreach (ServiceController controller in services)
                {
                    controller.Dispose();
                }
            }
        }
    }
}

Ответы [ 3 ]

81 голосов
/ 20 октября 2010

Вы можете использовать метод ServiceController.GetServices(), чтобы получить все службы на компьютере, а затем просмотреть их, чтобы узнать, существует ли один с именем, который вы ищете:

bool DoesServiceExist(string serviceName, string machineName)
{
    ServiceController[] services = ServiceController.GetServices(machineName);
    var service = services.FirstOrDefault(s => s.ServiceName == serviceName);
    return service != null;
}

Метод расширения FirstOrDefault() (от System.Linq) вернет либо первую службу с заданным именем, либо null, если совпадений нет.


Для решения проблемы скорости:

Разница между двумя подходами для одного вызова метода незначительна, независимо от того, найдена служба или нет.Это будет проблемой только в том случае, если вы вызываете этот метод тысячи раз, и в этом случае получите список служб один раз и запомните его.

15 голосов
/ 22 мая 2014

Такой же подход, как и у adrianbanks, но немного более компактный код. Если вы используете LINQ, вы можете использовать любое утверждение, чтобы вернуть то, что вы хотите. Кроме того, если вы проверяете на локальном компьютере, нет необходимости указывать имя компьютера.

bool DoesServiceExist(string serviceName)
{
   return ServiceController.GetServices().Any(serviceController => serviceController.ServiceName.Equals(serviceName));
}
4 голосов
/ 19 мая 2016

Построен поверх ответа Майка.Та же концепция, что и Dictionary.TryGetValue .

    /// <summary>
    /// Gets a <see cref="ServiceController"/> given the specified <see cref="pServiceName"/>.
    /// </summary>
    /// <param name="pServiceName">The name of the service.</param>
    /// <param name="pService">The <see cref="ServiceController"/> associated with the name.</param>
    /// <returns>
    /// <see cref="bool.True"/> if the <see cref="ServiceController"/> exists; otherwise <see cref="bool.False"/>.
    /// </returns>
    private static bool TryGetService(string pServiceName, out ServiceController pService)
    {
        pService = ServiceController.GetServices()
            .FirstOrDefault(serviceController => serviceController.ServiceName == pServiceName);

        return pService != null;
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...