如何使用delphi提高WMI性能? [英] How can I improve the WMI performance using delphi?

查看:171
本文介绍了如何使用delphi提高WMI性能?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写了一个简单的函数来检索使用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} 

的示例应用程序
诊断,
SysUtils,
ActiveX,
ComObj,
变体;

函数GetWMIInfo(const WMIClass,WMIProperty:string):string;
var
sWbemLocator:OLEVariant;
sWMIService:OLEVariant;
sWbemObjectSet:OLEVariant;
sWbemObject:OLEVariant;
oEnum:IEnumvariant;
iValue:LongWord;
开始;
结果:='';
sWbemLocator:= CreateOleObject('WbemScripting.SWbemLocator');
sWMIService:= sWbemLocator.ConnectServer('','root\CIMV2','','');
sWbemObjectSet:= sWMIService.ExecQuery('SELECT * FROM'+ WMIClass,'WQL');
oEnum:= IUnknown(sWbemObjectSet._NewEnum)as IEnumVariant;
如果oEnum.Next(1,sWbemObject,iValue)= 0,那么
结果:= sWbemObject.Properties_.Item(WMIProperty).Value;
结束

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;
结束
除了
在E:Exception do
Writeln(E.Classname,':',E.Message);
结束
Readln;
结束。


解决方案

这些是提高WMI性能的一些提示

1))将调用利用到 CreateOleObject



2。)重新使用WMI连接



一个更昂贵的任务是连接到WMI服务,所以重用这个连接,而不是每次调用函数创建一个连接。



3。)仅检索要使用的列



检索WMI的每个属性都有不同的来源,如Windows注册表,WinAPi等,限制列将提高性能。阅读这篇文章了解更多信息 如何获取WMI数据的来源



4。)使用 WBEM_FLAG_FORWARD_ONLY 标志



按照上述提示,我重写了您的示例应用程序

  { $ APPTYPE CONSOLE} 

使用
诊断,
SysUtils,
ActiveX,
ComObj,
变体;

var
FSWbemLocator:OLEVariant;
FWMIService:OLEVariant;

函数GetWMIInfo(const WMIClass,WMIProperty:string):string;
const
wbemFlagForwardOnly = $ 00000020;
var
FWbemObjectSet:OLEVariant;
FWbemObject:OLEVariant;
oEnum:IEnumvariant;
iValue:LongWord;
开始;
结果:='';
FWbemObjectSet:= FWMIService.ExecQuery(格式('从%s'选择%s,[WMIProperty,WMIClass]),'WQL',wbemFlagForwardOnly);
oEnum:= IUnknown(FWbemObjectSet._NewEnum)as IEnumVariant;
如果oEnum.Next(1,FWbemObject,iValue)= 0,那么
结果:= FWbemObject.Properties_.Item(WMIProperty).Value;
结束

var
SW:TStopwatch;

begin
try
CoInitialize(nil);
try
SW.Reset;
SW.Start;
FSWbemLocator:= CreateOleObject('WbemScripting.SWbemLocator');
FWMIService:= FSWbemLocator.ConnectServer('localhost','root\CIMV2','','');
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;
结束
除了
在E:EOleException do
Writeln(Format('EOleException%s%x',[E.Message,E.ErrorCode]));
在E:异常do
Writeln(E.Classname,':',E.Message);
结束
Readln;
结束。

执行从1245到180 ms(在笔记本电脑上)。


I wrote a simple function to retrieve system information using the WMI, passing as parameter the class and the property name. when I execute the function like this

  Writeln('Procesor Id '+GetWMIInfo('Win32_Processor','Name'));
  Writeln('Mother Board Serial '+GetWMIInfo('Win32_BaseBoard','SerialNumber'));
  Writeln('BIOS Version '+GetWMIInfo('Win32_BIOS','Version'));

The execution time is about 1300 ms.

I need retrieve a lot of additional information, So Is possible reduce the time of execution of this function?

This is a sample application with the function

{$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.

解决方案

These are some tips to improve the WMI performance

1.) Reutilize the call to CreateOleObject

2.) Reuse the WMI Connection

One of more expensive tasks is make a connection to the WMI services, so reutilize that conneciton instead of create one conneciton each time which call the function.

3.) Only retrieve the columns which you want to use

Every property which retrieve the WMI has different sources like the Windows registry, the WinAPi and so on, restricting the columns will improve the performance. read this article for more info How obtain the source of the WMI Data

4.) Use the WBEM_FLAG_FORWARD_ONLY flag when you execute the WQL sentence.

Following the above tips I rewrote your sample app

{$APPTYPE CONSOLE}

uses
  Diagnostics,
  SysUtils,
  ActiveX,
  ComObj,
  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', 'root\CIMV2', '', '');
      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:EOleException do
        Writeln(Format('EOleException %s %x', [E.Message,E.ErrorCode]));
    on E:Exception do
        Writeln(E.Classname, ':', E.Message);
 end;
 Readln;
end.

And the execution goes from 1245 to 180 ms (on my laptop).

这篇关于如何使用delphi提高WMI性能?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆