Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/cmake/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
从Delphi访问BcdStore_Delphi_Wmi_Bcdstore - Fatal编程技术网

从Delphi访问BcdStore

从Delphi访问BcdStore,delphi,wmi,bcdstore,Delphi,Wmi,Bcdstore,我正试图将这个代码片段转换成Delphi,我被困在ColoObject中每个objWBL的上 if not objBcdStore.EnumerateObjects( &h10200003, colObjects ) then WScript.Echo "ERROR objBcdStore.EnumerateObjects( &h10200003 ) failed." WScript.Quit(1) end if for each objWBL in colOb

我正试图将这个代码片段转换成Delphi,我被困在ColoObject中每个objWBL的

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翻译(注意,必须是管理员才能运行):

定义为

boolean EnumerateObjects(
  [in]   uint32 Type,
  [out]  BcdObject Objects[]
);
我不知道如何在Delphi中遍历BcdObject数组。

您必须使用and函数来获取由
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引导加载程序
对象,我们无法找出哪些对象是“当前”对象。正如我最终发现的(多亏了2008年7月发行的TechNet杂志上的文章),正确的方法是直接通过它的已知ID打开loader对象(这也是一个隐藏得很好但并不广为人知的方法。我在著名的BCD GUI上找到的唯一官方文档是document)

下面的示例代码首先打开BCD WMI对象。然后,它打开默认存储并显示
{current}
引导条目对象的信息(由已知ID访问)

接下来,它打开
Windows引导管理器
对象(通过使用其已知ID),读取其
DefaultObject
元素以确定默认引导项的GUID,根据其GUID打开此对象并显示信息

ShowLoaderInfo
仅显示
ID
(GUID)、
Description
NumberOfProcessors
(这是我想从BCD获得的信息)。这里有一个有趣的技巧,后者是
bcdintegreement
类型,它通过Integer属性返回其值,具有一个“特性”,即返回的值不是整数而是字符串。报告中的说明解释了:

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

(是的,太棒了!为什么它必须是64位的?20亿处理器还不够吗?)

有关受支持的
Windows引导加载程序
元素的完整列表,请参阅


我想你试过“for x in y do z()”语法,但没有成功?事实上,我没有。但是,它不起作用:“[DCC Error]Unit44.pas(55):E2430 for in语句不能对集合类型'OleVariant'进行操作。”我认为OleVariant数组和for in都不起作用,但我只是想知道。
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;
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.