WMI call takes too much time when system Starts/ReStarts

后端 未结 3 1679
醉梦人生
醉梦人生 2021-01-22 16:44

I want to get the path of the Windows Service,

var managementObjectSearcher = new ManagementObjectSearcher(\"Select * from Win32_Service where serviceName = MySe         


        
3条回答
  •  小鲜肉
    小鲜肉 (楼主)
    2021-01-22 17:16

    Since you're retrieving the service by Name, which a key property of the Win32_Service class, try retrieving the instance directly instead of searching for it:

    string GetMyServicePath()
    {
        string path = "Win32_Service.Name=\"MyService\"";
    
        using (ManagementObject service = new ManagementObject(path))
            return (string) service.GetPropertyValue("PathName");
    }
    

    Here's a quick benchmark I threw together to compare direct retrieval vs. searching:

    private const int LoopIterations = 1000;
    
    private const string ServiceClass = "Win32_Service";
    private const string ServiceName = "MyService";
    private const string ServiceProperty = "PathName";
    
    private static readonly string ServicePath = string.Format("{0}.Name=\"{1}\"", ServiceClass, ServiceName);
    private static readonly string ServiceQuery = string.Format(
        "SELECT {0} FROM {1} Where Name=\"{2}\"",
        ServiceProperty, ServiceClass, ServiceName
    );
    private static ManagementObjectSearcher ServiceSearcher = new ManagementObjectSearcher(ServiceQuery);
    
    static void Main(string[] args)
    {
        var watch = new Stopwatch();
    
        watch.Start();
        for (int i = 0; i < LoopIterations; i++)
        {
            var servicePath = GetServicePathByKey();
        }
        watch.Stop();
        Console.WriteLine(
            "{0:N0} iterations of GetServicePathByKey() took {1:N0} milliseconds",
            LoopIterations, watch.ElapsedMilliseconds
        );
    
        watch.Restart();
        for (int i = 0; i < LoopIterations; i++)
        {
            var servicePath = GetServicePathFromExistingSearcher();
        }
        watch.Stop();
        Console.WriteLine(
            "{0:N0} iterations of GetServicePathFromExistingSearcher() took {1:N0} milliseconds",
            LoopIterations, watch.ElapsedMilliseconds
        );
    
        watch.Restart();
        for (int i = 0; i < LoopIterations; i++)
        {
            var servicePath = GetServicePathFromNewSearcher();
        }
        watch.Stop();
        Console.WriteLine(
            "{0:N0} iterations of GetServicePathFromNewSearcher() took {1:N0} milliseconds",
            LoopIterations, watch.ElapsedMilliseconds
        );
    }
    
    static string GetServicePathByKey()
    {
        using (var service = new ManagementObject(ServicePath))
            return (string) service.GetPropertyValue(ServiceProperty);
    }
    
    static string GetServicePathFromExistingSearcher()
    {
        using (var results = ServiceSearcher.Get())
        using (var enumerator = results.GetEnumerator())
        {
            if (!enumerator.MoveNext())
                throw new Exception();
    
            return (string) enumerator.Current.GetPropertyValue(ServiceProperty);
        }
    }
    
    static string GetServicePathFromNewSearcher()
    {
        using (var searcher = new ManagementObjectSearcher(ServiceQuery))
        using (var results = searcher.Get())
        using (var enumerator = results.GetEnumerator())
        {
            if (!enumerator.MoveNext())
                throw new Exception();
    
            return (string) enumerator.Current.GetPropertyValue(ServiceProperty);
        }
    }
    

    Enumerating the searcher results directly is about as fast as I could make it, marginally faster than using a foreach block and twice as fast as using LINQ. On my 64-bit Windows 7 Professional system with the ServiceName constant set to Power I got these results:

    1,000 iterations of GetServicePathByKey() took 8,263 milliseconds
    1,000 iterations of GetServicePathFromExistingSearcher() took 64,265 milliseconds
    1,000 iterations of GetServicePathFromNewSearcher() took 64,875 milliseconds
    

提交回复
热议问题