检查特定计算机上是否存在服务而不使用异常处理

时间:2010-10-20 18:14:33

标签: c# windows-services

不知道是否有更好的方法可以做到这一点,所以这就是问题的原因。我可以使用以下代码检查特定计算机上是否存在服务:

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 个答案:

答案 0 :(得分:81)

您可以使用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


解决您的速度问题:

无论是否找到服务,单个方法调用的两种方法之间的差异可以忽略不计。如果你多次调用这个方法,这只会是一个问题 - 在这种情况下,获取一次服务列表并记住它。

答案 1 :(得分:15)

与adrianbanks相同,但代码稍微紧凑。 如果您使用的是LINQ,则可以使用任何语句返回您想要的内容。 此外,如果您在本地计算机上查看,则无需提供计算机名称。

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

答案 2 :(得分:4)

建立在迈克的答案之上。与 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;
    }