如何使用WMI与Delphi没有大幅增加应用程序的文件大小? [英] How do I use WMI with Delphi without drastically increasing the application's file size?

查看:169
本文介绍了如何使用WMI与Delphi没有大幅增加应用程序的文件大小?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用的是Delphi 2010,当我创建一个打印Hello World的控制台应用程序时,它需要111 kb。如果我想用Delphi查询WMI,我将WBEMScripting_TLB,ActiveX和Variants单元添加到我的项目中。如果我执行一个简单的WMI查询,我的可执行文件大小跳到810 kb。我

I am using Delphi 2010, and when I created a console application that prints "Hello World", it takes 111 kb. If I want to query WMI with Delp I add WBEMScripting_TLB, ActiveX, and Variants units to my project. If I perform a simple WMI query, my executable size jumps to 810 kb. I

有没有这样大量的文件大小来查询WMI?原谅我的无知,但为什么我没有C ++的这个问题?

Is there anyway to query WMI without such a large addition to the size of the file? Forgive my ignorance, but why do I not have this issue with C++?

这是我的代码:

program WMITest;

{$APPTYPE CONSOLE}

uses
  SysUtils,
  WBEMScripting_TLB,
  ActiveX,
  Variants;

function GetWMIstring(wmiHost, root, wmiClass, wmiProperty: string): string;
var
  Services: ISWbemServices;
  SObject: ISWbemObject;
  ObjSet: ISWbemObjectSet;
  SProp: ISWbemProperty;
  Enum: IEnumVariant;
  Value: Cardinal;
  TempObj: OLEVariant;
  loc: TSWbemLocator;
  SN: string;
  i: integer;
begin
  Result := '';
  i := 0;
  try
    loc := TSWbemLocator.Create(nil);
    Services := Loc.ConnectServer(wmiHost, root {'root\cimv2'}, '', '', '', '',
      0, nil);
    ObjSet := Services.ExecQuery('SELECT * FROM ' + wmiClass, 'WQL',
      wbemFlagReturnImmediately and wbemFlagForwardOnly, nil);
    Enum := (ObjSet._NewEnum) as IEnumVariant;
    if not VarIsNull(Enum) then
      try
        while Enum.Next(1, TempObj, Value) = S_OK do
        begin
          try
            SObject := IUnknown(TempObj) as ISWBemObject;
          except SObject := nil;
          end;
          TempObj := Unassigned;
          if SObject <> nil then
          begin
            SProp := SObject.Properties_.Item(wmiProperty, 0);
            SN := SProp.Get_Value;
            if not VarIsNull(SN) then
            begin
              if varisarray(SN) then
              begin
                for i := vararraylowbound(SN, 1) to vararrayhighbound(SN, 1) do
                  result := vartostr(SN[i]);
              end
              else
                Result := SN;
              Break;
            end;
          end;
        end;
        SProp := nil;
      except
        Result := '';
      end
    else
      Result := '';
    Enum := nil;
    Services := nil;
    ObjSet := nil;
  except
    on E: Exception do
      Result := e.message;
  end;
end;

begin
  try
    WriteLn('hello world');
    WriteLn(GetWMIstring('.', 'root\CIMV2', 'Win32_OperatingSystem',
      'Caption'));
    WriteLn('done');

  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

更新:
当我编译以下来自MSDN的示例与Microsoft Visual C ++ 2008(控制台应用程序),它是76 kb。

UPDATE: When I compile the following sample from MSDN with Microsoft Visual C++ 2008 (console application), it is 76 kb.

推荐答案

@Mick,您可以访问WMI而不从Delphi导入WBEMScripting,使用 IBindCtx IMoniker 界面。

@Mick, you can access the WMI without import the WBEMScripting from Delp using the IBindCtx and IMoniker interfaces.

检查这个简单的代码(在Delphi 2010和Windows 7中测试),exe文件大小为174 kb。

Check this simple code (Tested in Delphi 2010 and Windows 7), the exe file size is 174 kb.

program WmiTest;

{$APPTYPE CONSOLE}


uses
  SysUtils
  ,ActiveX
  ,ComObj
  ,Variants;


function GetWMIstring(wmiHost, root, wmiClass, wmiProperty: string): string;
var
  objWMIService : OLEVariant;
  colItems      : OLEVariant;
  colItem       : OLEVariant;
  oEnum         : IEnumvariant;
  iValue        : LongWord;

  function GetWMIObject(const objectName: String): IDispatch;
  var
    chEaten: Integer;
    BindCtx: IBindCtx;//for access to a bind context
    Moniker: IMoniker;//Enables you to use a moniker object
  begin
    OleCheck(CreateBindCtx(0, bindCtx));
    OleCheck(MkParseDisplayName(BindCtx, StringToOleStr(objectName), chEaten, Moniker));//Converts a string into a moniker that identifies the object named by the string
    OleCheck(Moniker.BindToObject(BindCtx, nil, IDispatch, Result));//Binds to the specified object
  end;

begin
  objWMIService := GetWMIObject(Format('winmgmts:\\%s\%s',[wmiHost,root]));
  colItems      := objWMIService.ExecQuery(Format('SELECT * FROM %s',[wmiClass]),'WQL',0);
  oEnum         := IUnknown(colItems._NewEnum) as IEnumVariant;
  while oEnum.Next(1, colItem, iValue) = 0 do 
  begin
     Result:=colItem.Properties_.Item(wmiProperty, 0); //you can improve this code  ;) , storing the results in an TString.
  end;
end;

begin
 try
    CoInitialize(nil);
    try         
      WriteLn(GetWMIstring('.', 'root\CIMV2', 'Win32_OperatingSystem','Caption'));
      Readln;
    finally
    CoUninitialize;
    end;
 except
    on E:Exception do
    Begin
        Writeln(E.Classname, ': ', E.Message);
        Readln;
    End;
  end;
end.

这篇关于如何使用WMI与Delphi没有大幅增加应用程序的文件大小?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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