首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在Delphi中访问BcdStore

在Delphi中访问BcdStore
EN

Stack Overflow用户
提问于 2011-09-23 00:08:11
回答 2查看 1.2K关注 0票数 3

我试图将这段代码转换成Delphi,但我被for each objWBL in colObjects卡住了。

代码语言:javascript
复制
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才能运行它):

代码语言:javascript
复制
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被定义为

代码语言:javascript
复制
boolean EnumerateObjects(
  [in]   uint32 Type,
  [out]  BcdObject Objects[]
);

我不知道如何在Delphi语言中遍历BcdObject数组。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-09-23 00:28:53

必须使用VarArrayLowBoundVarArrayHighBound函数来获取EnumerateObjects函数返回的变量数组的边界,然后才能使用for循环迭代数组的元素。

检查此示例

代码语言:javascript
复制
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;
票数 8
EN

Stack Overflow用户

发布于 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)、DescriptionNumberOfProcessors (这是我想从BCD获得的信息)。这里一个有趣的技巧是,后者是BcdIntegerElement类型,它通过Integer属性返回它的值,具有返回值不是整数而是字符串的“特性”。MSDN的一份报告解释道:

元素的整数值。该值作为字符串传递,因为Automation本身不支持64位整数。

(是的,太棒了!为什么一定要是64位的呢?20亿个处理器还不够吗?)

有关支持的Windows Boot Loader元素的完整列表,请参阅BcdOSLoaderElementTypes

代码语言:javascript
复制
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.
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7517965

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档