我试图将这段代码转换成Delphi,但我被for each objWBL in colObjects卡住了。
if not objBcdStore.EnumerateObjects( &h10200003, colObjects ) then
WScript.Echo "ERROR objBcdStore.EnumerateObjects( &h10200003 ) failed."
WScript.Quit(1)
end if
for each objWBL in colObjects
WScript.Echo ""
WScript.Echo "Windows Boot Loader"
WScript.Echo "-------------------"
WScript.Echo "identifier " & GetBcdId( objWBL.Id )
If objWBL.Id = current then
if not objWBL.GetElement(BcdOSLoaderInteger_NumberOfProcessors, objElement ) then
WScript.Echo "ERROR WBL GetElement for " & Hex(BcdOSLoaderInteger_NumberOfProcessors) & " failed."
WScript.Quit(1)
end if
WScript.Echo "numproc " & objElement.Integer
if not objWBL.GetElement(BcdOSLoaderBoolean_UseBootProcessorOnly, objElement ) then
WScript.Echo "ERROR WBL GetElement for " & Hex(BcdOSLoaderBoolean_UseBootProcessorOnly) & " failed."
WScript.Quit(1)
end if
WScript.Echo "onecpu " & objElement.Boolean
end if
next我的部分q&d翻译(注意,必须是Admin才能运行它):
uses
OleAuto,
ActiveX;
function GetObject(const objectName: String): IDispatch;
var
bindCtx: IBindCtx;
moniker: IMoniker;
chEaten: Integer;
begin
OleCheck(CreateBindCtx(0, bindCtx));
OleCheck(MkParseDisplayName(bindCtx, StringToOleStr(objectName), chEaten, moniker));
OleCheck(moniker.BindToObject(bindCtx, nil, IDispatch, Result));
end;
procedure TForm44.btnClick(Sender: TObject);
var
colObjects : OleVariant;
objBcdStore : OleVariant;
objWMIService: OleVariant;
begin
objWMIService := GetObject('winmgmts:{impersonationlevel=Impersonate,(Backup,Restore)}!root/wmi:BcdStore');
if not objWMIService.OpenStore('', objBcdStore) then
Caption := 'error'
else begin
objBcdStore.EnumerateObjects($10200003, colObjects);
//???
end;
end;EnumerateObjects被定义为
boolean EnumerateObjects(
[in] uint32 Type,
[out] BcdObject Objects[]
);我不知道如何在Delphi语言中遍历BcdObject数组。
发布于 2011-09-23 00:28:53
必须使用VarArrayLowBound和VarArrayHighBound函数来获取EnumerateObjects函数返回的变量数组的边界,然后才能使用for循环迭代数组的元素。
检查此示例
Uses
ComObj,
ActiveX;
function GetObject(const objectName: String): IDispatch;
var
bindCtx: IBindCtx;
moniker: IMoniker;
chEaten: Integer;
begin
OleCheck(CreateBindCtx(0, bindCtx));
OleCheck(MkParseDisplayName(bindCtx, StringToOleStr(objectName), chEaten, moniker));
OleCheck(moniker.BindToObject(bindCtx, nil, IDispatch, Result));
end;
procedure TForm44.Button1Click(Sender: TObject);
var
colObjects : OleVariant;
objBcdStore : OleVariant;
objWMIService: OleVariant;
i : Integer;
objWBL : OleVariant;
begin
objWMIService := GetObject('winmgmts:{impersonationlevel=Impersonate,(Backup,Restore)}!root/wmi:BcdStore');
if not objWMIService.OpenStore('', objBcdStore) then
Caption := 'error'
else
begin
objBcdStore.EnumerateObjects($10200003, colObjects);
if not VarIsNull(colObjects) and VarIsArray(colObjects) then
for i := VarArrayLowBound(colObjects, 1) to VarArrayHighBound(colObjects, 1) do
begin
objWBL:=colObjects[i];
//do your stuff here
end;
end;
end;发布于 2011-09-23 17:52:26
感谢RRUZ的回答--我学到了一些新东西--但遗憾的是,正确的答案是“不要那样做”(多么典型!)。
事实证明,通过枚举Windows Boot Loader对象,无法找出哪个对象是“当前”对象。正如我最终发现的(感谢2008年7月的TechNet杂志上的Hey, Scripting Guy!文章),正确的方法是直接通过加载程序对象的众所周知的ID打开它(同样,这是众所周知的隐藏的,不是众所周知的。我在著名的BCD上找到的唯一官方文档是Boot Configuration Data in Windows Vista文档。)
下面的示例代码首先打开BCD WMI对象。然后,它打开默认存储并显示{current}引导条目对象的信息(通过众所周知的ID访问)。
接下来,它打开Windows Boot Manager对象(通过使用其众所周知的ID),读取其DefaultObject元素以确定默认引导条目的GUID,通过其GUID打开该对象并显示信息。
ShowLoaderInfo只显示ID (GUID)、Description和NumberOfProcessors (这是我想从BCD获得的信息)。这里一个有趣的技巧是,后者是BcdIntegerElement类型,它通过Integer属性返回它的值,具有返回值不是整数而是字符串的“特性”。MSDN的一份报告解释道:
元素的整数值。该值作为字符串传递,因为Automation本身不支持64位整数。
(是的,太棒了!为什么一定要是64位的呢?20亿个处理器还不够吗?)
有关支持的Windows Boot Loader元素的完整列表,请参阅BcdOSLoaderElementTypes。
program ShowBCDInfo;
{$APPTYPE CONSOLE}
uses
SysUtils,
ComObj,
ActiveX;
const
Description = $12000004; //http://msdn.microsoft.com/en-us/aa362652(v=VS.85)
UseBootProcessorOnly = $26000060; //http://msdn.microsoft.com/en-us/aa362641(v=VS.85)
NumberOfProcessors = $25000061;
ForceMaximumProcessors = $26000062;
ProcessorConfigurationFlags = $25000063;
DefaultObject = $23000003; //http://msdn.microsoft.com/en-us/aa362641(v=VS.85)
CurrentGUID = '{fa926493-6f1c-4193-a414-58f0b2456d1e}'; //http://msdn.microsoft.com/en-us/windows/hardware/gg463059.aspx
WBMGUID = '{9dea862c-5cdd-4e70-acc1-f32b344d4795}';
function GetObject(const objectName: String): IDispatch;
var
bindCtx: IBindCtx;
moniker: IMoniker;
chEaten: Integer;
begin
OleCheck(CreateBindCtx(0, bindCtx));
OleCheck(MkParseDisplayName(bindCtx, StringToOleStr(objectName), chEaten, moniker));
OleCheck(moniker.BindToObject(bindCtx, nil, IDispatch, Result));
end;
procedure ShowLoaderInfo(const name: string; const obj: OleVariant);
var
objElement: OleVariant;
begin
Writeln(Format('%s ID: %s', [name, string(obj.id)]));
if obj.GetElement(Description, objElement) then
Writeln(Format('Description: %s', [objElement.String]));
if obj.GetElement(NumberOfProcessors, objElement) then
Writeln(Format('NumProc: %s', [objElement.Integer]));
end;
procedure ShowBcdInfo;
var
objBcdStore : OleVariant;
objWBL : OleVariant;
objWBM : OleVariant;
objWMIService: OleVariant;
begin
objWMIService := GetObject('winmgmts:{(Backup,Restore)}\\.\root\wmi:BcdStore');
if not objWMIService.OpenStore('', objBcdStore) then
Writeln('*** error opening store')
else begin
if objBcdStore.OpenObject(CurrentGUID, objWBL) then
ShowLoaderInfo('{current}', objWBL);
if objBcdStore.OpenObject(WBMGuid, objWBM) and
objWBM.GetElement(DefaultObject, objWBL) and
objBcdStore.OpenObject(string(objWBL.ID), objWBL)
then
ShowLoaderInfo('{default}', objWBL);
end;
end;
begin
try
OleInitialize(nil);
try
ShowBCDInfo;
finally OleUninitialize; end;
Readln;
except
on E:Exception do
Writeln(E.Classname, ': ', E.Message);
end;
end.https://stackoverflow.com/questions/7517965
复制相似问题