加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

如何使用delphi提高WMI性能?

发布时间:2020-12-15 06:09:57 所属栏目:大数据 来源:网络整理
导读:我写了一个简单的函数来检索使用WMI的系统信息,作为参数传递类和属性名称.当我执行这样的功能 Writeln('Procesor Id '+GetWMIInfo('Win32_Processor','Name')); Writeln('Mother Board Serial '+GetWMIInfo('Win32_BaseBoard','SerialNumber')); Writeln('BI
我写了一个简单的函数来检索使用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('','rootCIMV2','','');
  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(在我的笔记本电脑上).

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读