我写了一个简单的函数来检索使用WMI的系统信息,作为参数传递类和属性名称.当我执行这样的功能
Writeln('Procesor Id '+GetWMIInfo('Win32_Processor','Name')); Writeln('Mother Board Serial '+GetWMIInfo('Win32_BaseBoard','SerialNumber')); Writeln('BIOS Version '+GetWMIInfo('Win32_BIOS','Version'));
执行时间约为1300 ms.
我需要检索大量的附加信息,那么可以减少执行这个功能的时间吗?
这是具有该功能的示例应用程序
{$APPTYPE CONSOLE} uses Diagnostics,SysUtils,ActiveX,ComObj,Variants; function GetWMIInfo(const WMIClass,WMIProperty:string): string; var sWbemLocator : OLEVariant; sWMIService : OLEVariant; sWbemObjectSet: OLEVariant; sWbemObject : OLEVariant; oEnum : IEnumvariant; iValue : LongWord; begin; Result:=''; sWbemLocator := CreateOleObject('WbemScripting.SWbemLocator'); sWMIService := sWbemLocator.ConnectServer('','root\CIMV2','',''); sWbemObjectSet:= sWMIService.ExecQuery('SELECT * FROM '+WMIClass,'WQL'); oEnum := IUnknown(sWbemObjectSet._NewEnum) as IEnumVariant; if oEnum.Next(1,sWbemObject,iValue) = 0 then Result:=sWbemObject.Properties_.Item(WMIProperty).Value; end; var SW : TStopwatch; begin try CoInitialize(nil); try SW.Reset; SW.Start; Writeln('Procesor Id '+GetWMIInfo('Win32_Processor','Name')); Writeln('Mother Board Serial '+GetWMIInfo('Win32_BaseBoard','SerialNumber')); Writeln('BIOS Version '+GetWMIInfo('Win32_BIOS','Version')); SW.Stop; Writeln('Elapsed ms '+FormatFloat('#,0.000',SW.Elapsed.TotalMilliseconds)); finally CoUninitialize; end; except on E:Exception do Writeln(E.Classname,':',E.Message); end; Readln; end.
解决方法
这些是提高WMI性能的一些提示
1)将电话重新列为CreateOleObject
2.)重新使用WMI连接
一个更昂贵的任务是连接到WMI服务,所以重用这个连接,而不是每次调用该函数创建一个连接.
3.)仅检索要使用的列
检索WMI的每个属性都有不同的来源,如Windows注册表,WinAPi等,限制列将提高性能.阅读这篇文章了解更多信息How obtain the source of the WMI Data
4.)执行WQL句时,使用WBEM_FLAG_FORWARD_ONLY标志.
按照上述提示,我重写了您的示例应用程序
{$APPTYPE CONSOLE} uses Diagnostics,Variants; var FSWbemLocator : OLEVariant; FWMIService : OLEVariant; function GetWMIInfo(const WMIClass,WMIProperty:string): string; const wbemFlagForwardOnly = $00000020; var FWbemObjectSet: OLEVariant; FWbemObject : OLEVariant; oEnum : IEnumvariant; iValue : LongWord; begin; Result:=''; FWbemObjectSet:= FWMIService.ExecQuery(Format('Select %s from %s',[WMIProperty,WMIClass]),'WQL',wbemFlagForwardOnly); oEnum := IUnknown(FWbemObjectSet._NewEnum) as IEnumVariant; if oEnum.Next(1,FWbemObject,iValue) = 0 then Result:=FWbemObject.Properties_.Item(WMIProperty).Value; end; var SW : TStopwatch; begin try CoInitialize(nil); try SW.Reset; SW.Start; FSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator'); FWMIService := FSWbemLocator.ConnectServer('localhost',''); Writeln('Procesor Id '+GetWMIInfo('Win32_Processor',SW.Elapsed.TotalMilliseconds)); finally CoUninitialize; end; except on E:EOleException do Writeln(Format('EOleException %s %x',[E.Message,E.ErrorCode])); on E:Exception do Writeln(E.Classname,E.Message); end; Readln; end.
并且执行从1245到180ms(在我的笔记本电脑上).