获取ManagementObject

时间:2017-04-20 14:51:14

标签: c# winapi optimization wmi-query

我有一个返回远程机器上的服务列表的方法。我使用ManagementObjectSearcher.Get()和WIN32查询获取ManagementObjectCollection。然后在foreach循环中创建我的Service类的实例并将其添加到结果列表中。在初始化新服务时,我使用GetPropertyValue(字符串)获取ManagementObject属性。我面临的问题是这个过程非常缓慢。我认为GetPropertyValue很慢(我每次循环使用它7次)。是否有更快的方法从ManagementObject类获取属性?

 var query = new ObjectQuery("Select Name, DisplayName, ProcessId, Description, State, StartMode, StartName From Win32_Service");
                ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query);
                ManagementObjectCollection allServices = searcher.Get();
                foreach (ManagementObject p in allServices)
                {Service newService = new Service{ Name = p.GetPropertyValue("Name"),etc...} result.Add(newService);}

1 个答案:

答案 0 :(得分:1)

我一直在与此作斗争,试图了解什么是如此缓慢。

我编写了一个测试程序,几乎所有东西都使用了秒表时间。 我有一个从Win32_PnPSignedDriver返回3个设备的wql查询。 我使用了三种不同的方法从查询中检索结果。

ManagementObjectCollection queryResults;
ManagementObjectSearcher searcher = new ManagementObjectSearcher();
var myWql = "SELECT * FROM Win32_PnPSignedDriver WHERE ..."
searcher.Scope = new ManagementScope(@"root\CIMV2");
searcher.Query = new WqlObjectQuery(wmiQry);
queryResults = searcher.Get(); 

searcher.Get()很快。

我使用三种方法从ManagementObjectCollection queryResults中检索数据。

  1. foreach(queryResults中的ManagementBaseObject设备){}
  2. IEnumerator enumerator = queryResults.GetEnumerator();而 (enumerator.MoveNext()){}
  3. queryResults.CopyTo(deviceArray,0); foreach(deviceArray中的var btDevice)
  4. 首次测试: 方法1:非常慢 - 超过3000执行空循环。 方法2:非常快。 1毫秒 方法3:也非常快。 0毫秒。

    然后我在测试中看到了错误。第一个循环计算了集合中的对象,然后框架记住了这一点。如果我多次执行方法1,只有初始循环很慢,但是重复foreach是0到1毫秒。

    我重构了我的测试,在每次获取数据之前重新执行查询。 方法1:每次都很慢。 方法2:每次都慢。 方法3:我的秒表计时报告0到1毫秒,但我注意到执行时间更长。 ???

    深入研究我编码的内容,我看到我没有计算以下内容:

    ManagementObject[] deviceArray = new ManagementObject[queryResults.Count];
    

    实际上是两个命令:

    var count = queryResults.Count;
    ManagementObject[] deviceArray = new ManagementObject[count];
    

    我分别计时,看到queryResults.Count几乎一直占用。经常> 3000毫秒。

    然后我硬编码了数组的大小以避免调用:queryResults.Count

    然而,当我执行

    queryResults.CopyTo(deviceArray, 0);  
    

    CopyTo方法仍然需要知道ManagementObjectCollection中有多少项,现在CopyTo采用>之前为0或1毫秒的3000毫秒。

    所以,它会出现ManagementObjectCollection。 get_Count是瓶颈,我无论如何都不知道检索结果而不会导致执行Count getter。