如何在不显着增加应用程序文件大小的情况下将 WMI 与 Delphi 结合使用? [英] How do I use WMI with Delphi without drastically increasing the application's file size?
问题描述
我使用的是 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 {'rootcimv2'}, '', '', '', '',
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('.', 'rootCIMV2', '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,使用 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('.', 'rootCIMV2', '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屋!