Подтвердить что ты не робот

Проверьте, существует ли служба на конкретной машине без использования обработки исключений

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

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, которое было бы приемлемым.

EDIT: Вот пример консольного приложения С#, чтобы проверить производительность моего примера, а также образец кода 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();
                }
            }
        }
    }
}
4b9b3361

Ответ 1

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


Чтобы решить проблему с вашей скоростью:

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

Ответ 2

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

bool DoesServiceExist(string serviceName)
{
   return ServiceController.GetServices().Any(serviceController => serviceController.ServiceName.Equals(serviceName));
}

Ответ 3

Построенный поверх Майка. Та же концепция, что и 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;
    }