Как я использую WMI с Delphi, решительно не увеличивая размер файла приложения?

Я использую Delphi 2010, и когда я создал консольное приложение, которое печатает "Привет Мир", требуется 111 Кбит. Если я хочу запросить WMI с Delphi, я добавляю WBEMScripting_TLB, ActiveX и единицы Вариантов к моему проекту. Если я выполняю простой запрос WMI, мой исполняемый размер переходит к 810 Кбитам. Я

Там должен так или иначе запросить WMI без такого большого дополнения к размеру файла? Простите мое незнание, но почему у меня нет этой проблемы с 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 Кбит.

13
задан Mick 4 May 2010 в 11:47
поделиться

5 ответов

@Mick, вы можете получить доступ к WMI без импорта сценариев WBEMS из Delphi, используя интерфейсы IBindCtx и IMoniker .

Проверьте этот простой код (протестирован в Delphi 2010 и Windows 7), размер exe-файла составляет 174 КБ.

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.
27
ответ дан 1 December 2019 в 19:23
поделиться

Ну, я не знаю о WBEMScripting_TLB, но ActiveX.pas - довольно большой модуль. На моей установке D2010 почти 7000 строк. Если вам нужно внести какое-либо значительное количество этого в свой код, вы можете ожидать, что это добавит несколько сотен КБ к вашему размеру EXE.

Насколько велик TLB, кстати?

0
ответ дан 1 December 2019 в 19:23
поделиться

ActiveX и / или варианты добавят не более 36 КБ.
Это WBEMScripting_TLB , который добавляет в ваш проект примерно 650 КБ .
Он не огромен по количеству строк кода, но помимо объявления нескольких классов, интерфейсов и констант, он включает в себя OleServer .
И ТО приносит весь блок управления с его тяжелым багажом .

6
ответ дан 1 December 2019 в 19:23
поделиться

Разница, которую вы видите, отчасти заключается в том, что VC ++ по умолчанию использует динамически подключаемые библиотеки времени выполнения; библиотеки времени выполнения загружаются из библиотек DLL при запуске приложения, и поэтому код отсутствует в исполняемом файле.

Delphi, OTOH, по умолчанию связывается со всем кодом библиотеки времени выполнения, если вы не выполняете сборку с включенными пакетами времени выполнения. Эта разница в конфигурациях по умолчанию будет составлять большую часть различий в размерах между исполняемыми файлами.

1
ответ дан 1 December 2019 в 19:23
поделиться

когда delphi создает исполняемый файл, он статически связывается со средой выполнения delphi библиотеки. это приводит к увеличению размера исполняемого файла, однако, поскольку rtl статически связан, развертывание упрощается, и есть элемент будущей проверки.

вы можете настроить delphi для использования пакетов времени выполнения, включив Сборка с пакетами времени выполнения в параметрах проекта / . однако вам необходимо убедиться, что пакеты delphi rtl доступны, и вы можете столкнуться с проблемами при отладке.

это статическое и динамическое связывание, вероятно, объясняет различия, которые вы наблюдаете между delphi и c ++.

2
ответ дан 1 December 2019 в 19:23
поделиться
Другие вопросы по тегам:

Похожие вопросы: