系统启动/重新启动时,WMI调用会花费太多时间
我想获得Windows服务的路径,
var managementObjectSearcher = new ManagementObjectSearcher("Select * from Win32_Service where serviceName = MyService");
这段代码是由其他一些服务的构造函数编写的……
当系统启动并运行时,一切正常,但是如果我重新启动系统,则为此调用设置StopWatch类,并显示它显示该服务因此调用需要35-45秒才能启动。
任何提高系统重启性能的建议……
Windows32_Services类不存在,因此假设您正在使用Win32_Service
WMI类,您可以提高性能,只返回您要使用的属性,在本例中为PathName
,因此将您的WQL句子更改为
SELECT PathName FROM Win32_Service Where Name='MyService'
UPDATE
对@Bacon的观察是非常正确的,因为您知道要检索的服务的名称,您可以构建Win32_Service的对象路径,它看起来像
Win32_Service.Name="ServiceName"
然后使用ManagementObject
类,您可以以最快的方式将实例检索到服务。
由于您是通过Name
( Win32_Service class
一个键属性)检索服务,因此请尝试直接检索实例而不是搜索它:
string GetMyServicePath() { string path = "Win32_Service.Name=\"MyService\""; using (ManagementObject service = new ManagementObject(path)) return (string) service.GetPropertyValue("PathName"); }
这是一个快速的基准测试,我把它直接检索与搜索比较:
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); } }
直接计算搜索结果的速度与我的速度一样快,比使用foreach
块快一点,速度比使用LINQ
快两倍。 在我的64位Windows 7 Professional系统上, ServiceName
常量设置为Power
我得到了以下结果:
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
如果是WMI的“延迟”困扰您,您不必使用WMI来获取服务的路径,即。 可执行名称。 您还可以P / invoke QueryServiceConfig 。
http://www.pinvoke.net/default.aspx/advapi32/queryserviceconfig.html