[英]Accessing BcdStore from Delphi
我正在嘗試將此代碼片段轉換為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翻譯(謹慎,必須是管理員才能運行它):
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;
boolean EnumerateObjects(
[in] uint32 Type,
[out] BcdObject Objects[]
);
我不知道如何在Delphi中遍歷BcdObject數組。
您必須使用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;
感謝RRUZ的回答 - 我學到了一些新東西 - 但遺憾的是,正確答案是“不要那樣做”(多么典型!)。
事實證明,通過枚舉Windows Boot Loader
對象,無法找出哪個對象是“當前”對象。 正如我最終發現的那樣(感謝嘿,腳本專家!來自TechNet雜志2008年7月刊的文章),正確的方法是直接用它眾所周知的ID打開加載器對象。 (這也是隱藏得很好而且不為人所知。我在着名的BCD GUID上找到的唯一官方文檔是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.
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.