系统启动/重新启动时,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类,您可以以最快的方式将实例检索到服务。

由于您是通过NameWin32_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