如何在不大幅增加应用程序文件大小的情况下将WMI与Delphi一起使用?
我使用的是Delphi2010,当我创建一个控制台应用程序来打印Hello World时,它需要111KB。如果我想用Delphi查询WMI,我会将WBEMU TLB、ActiveX和变体单元添加到我的项目中。如果我执行一个简单的WMI查询,我的可执行文件大小会跳到810KB。我 在不增加文件大小的情况下,是否仍可以查询WMI?原谅我的无知,但为什么我没有这个问题与C++ + < /P> 这是我的密码:如何在不大幅增加应用程序文件大小的情况下将WMI与Delphi一起使用?,delphi,wmi,Delphi,Wmi,我使用的是Delphi2010,当我创建一个控制台应用程序来打印Hello World时,它需要111KB。如果我想用Delphi查询WMI,我会将WBEMU TLB、ActiveX和变体单元添加到我的项目中。如果我执行一个简单的WMI查询,我的可执行文件大小会跳到810KB。我 在不增加文件大小的情况下,是否仍可以查询WMI?原谅我的无知,但为什么我没有这个问题与C++ + < /P> 这是我的密码: program WMITest; {$APPTYPE CONSOLE} uses S
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.
更新:
当我用微软Visual C++ 2008控制台应用程序编译时,它是76 kb.< /p> ,我不知道WBESCRIPPTIGN TLB,但是ActiveX.PAS是一个相当大的单元。在我的D2010安装上几乎有7000条线路。如果你必须在你的代码中加入大量的内容,那么你可以预期它会增加你的EXE大小几百K
顺便问一下,TLB有多大?ActiveX和/或变体最多会增加36KB。 WBEMU TLB为您的项目增加了大约650KB。 它的代码行并不多,但不仅仅是声明了相当多的类、接口和常量,它还包括OleServer。
这给整个控制单元带来了沉重的负担。@Mick,您可以使用和接口访问WMI,而无需从Delphi导入WBEMScript 检查这个在Delphi2010和Windows7中测试的简单代码,exe文件大小为174KB
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.
当delphi构建可执行文件时,它静态链接delphi运行时库。这将导致一个更大的可执行文件,但是由于rtl是静态链接的,部署更容易,并且有一个未来验证的元素 通过在项目/选项中启用“使用运行时包生成”,可以将delphi配置为使用运行时包。但是,您必须确保DelphiRTL包可用,并且在调试时可能会遇到问题
这种静态与运行时链接行为可能解释了在Delphi和C++之间的差异。
< P>你看到的差异,部分原因是因为VC++默认使用动态链接的运行库;运行时库是在应用程序运行时从DLL加载的,因此代码不在可执行文件中默认情况下,所有运行时库代码中都有Delphi、OTOH链接,除非您在生成时启用了运行时包。默认配置的这种差异将解释可执行文件之间的大小差异。当你用C++表示时,你使用的C++编译器是什么?C++ Builder?Visual C++?GCC?什么版本?为什么控制台应用程序打印“hello World”任何可执行的大小的有意义的数据点?它是一个参考框架,对于非德尔菲用户来说,熟悉C/C++的C++解决方案是VS 2008。当我从MSDN编译类似的示例时,大小是76 kb:VS2008。。。您可能有一些运行时DLL要与exe.True一起部署。再说一次,这已经不再是沉重的行李了。见鬼,整个大幅增加的可执行文件仍然可以放在1.44MB的软盘上!这样看。。。尽管如此,它还是增加了7倍,而且它不再适合360K软盘——实际上是失败的软盘-这正是我要找的@IanBoyd检查这篇文章GetWMIOObject中存在内存泄漏:StringToolEstrobObjectName没有匹配的SysFreeStringobjectName!