无法使用 WMI 在 Windows 2012 Server 上读取 BCDStore 信息

Posted

技术标签:

【中文标题】无法使用 WMI 在 Windows 2012 Server 上读取 BCDStore 信息【英文标题】:Cannot read BCDStore info on Windows 2012 Server using WMI 【发布时间】:2012-12-19 00:03:30 【问题描述】:

我们正在使用以下函数来获取当前引导配置指定的处理器数量。这个数字纯粹用于记录。

以下功能在 XP、Vista、7、2003 和 2008 上运行良好。但在 Windows 2012 Server 上运行失败。

// -1 = not implemented or not allowed
//  0 = not limited
// >0 = number of processors in the current boot entry
function Internal_GetBCDNumberOfProcessors: integer;
var
  objBcdStore  : OleVariant;
  objElement   : OleVariant;
  objWBL       : OleVariant;
  objWMIService: OleVariant;
begin
  // for more info, see: http://***.com/questions/7517965/accessing-bcdstore-from-delphi/7527164#7527164
  Result := -1;
  try
    objWMIService := GetObject('winmgmts:(Backup,Restore)\\.\root\wmi:BcdStore');
    if (not VarIsNull(objWMIService)) and
       boolean(objWMIService.OpenStore('', objBcdStore)) and
       (not VarIsNull(objBcdStore)) and
       boolean(objBcdStore.OpenObject('fa926493-6f1c-4193-a414-58f0b2456d1e', objWBL)) and
       (not VarIsNull(objWBL))
    then
      if objWBL.GetElement($25000061, objElement) and //<-- fails here on Server 2012
         (not VarIsNull(objElement))
      then
        Result := StrToIntDef(objElement.Integer, 0)
      else
        Result := 0;
  except
    on E: EOleSysError do
      Result := -1;
  end;
end;

如果我尝试在 Win2012 上运行它,objWBL.GetElement 会引发 EOleSysError 异常,并带有文本 OLE error D0000225。谷歌没有找到与此错误代码相关的任何有意义的东西:(

堆栈跟踪表明异常是在由 VarDispInvoke 调用的 DispatchInvoke 调用的 System.Win.ComObj.DispatchInvokeError 中触发的。

所有这些都是使用 XE2 复制的。我可以尝试用 XE3 重复这个问题,但我不相信 Delphi RTL 与它有任何关系。

有人知道这种行为的可能原因吗?

【问题讨论】:

你有更新 4 修补程序 1 吗? 是的,我应该有。我会仔细检查。 (Exe 是在构建服务器上构建的,应该安装了 U4H1。) UAC 开启还是关闭?进程提升还是不提升? UAC 打开,作为服务和提升的 GUI 进程进行测试。没有区别。 你可以尝试使用VbScript来获取错误描述,试试这个示例pastebin.com/ALmnk4R0 【参考方案1】:

GetElement 部分:

if objWBL.GetElement($25000061, objElement) and //<-- fails here on Server 2012
   (not VarIsNull(objElement))
then
  Result := StrToIntDef(objElement.Integer, 0)
else
  Result := 0;

可以替换为EnumerateElements:

if objWBL.EnumerateElements(objArray) then try
  for i := VarArrayLowBound(objArray, 1) to VarArrayHighBound(objArray, 1) do begin
    objElement := objArray[i];
    if objElement.Type = $25000061 then
      Exit(objElement.Integer);
  end;
finally VarClear(objArray); end;

这不会引发EOleException,但遗憾的是也找不到NumberOfProcessors 元素。

【讨论】:

以上是关于无法使用 WMI 在 Windows 2012 Server 上读取 BCDStore 信息的主要内容,如果未能解决你的问题,请参考以下文章

内网渗透-横向移动(smb&wmi)

转载 WMI方式:windows系统接入

Windows 8 上的 Wmi 安全性

win7系统中的WMI服务无法启动

使用 WMI 远程删除 Windows 7 网络打印机驱动程序

Windows Server 2008 中的 WMI 错误(WMI 提供程序)