bcdedit,bcdstore和powershell

时间:2013-06-03 18:32:37

标签: powershell bcdedit bcdstore

所以我可以在powershell脚本中编写bcd命令,就像我在cmd提示符中一样,例如:

bcdedit /default '{current}'

但是我需要一个执行此操作的脚本:

bcdedit /default '{current}'
bcdedit /set '{otherboot}' description "my description"

如果它没有这样做,那将是另一种方式:

bcdedit /default '{otherboot}'
bcdedit /set '{current}' description "my description"

我需要做的是在powershell中找到其他启动的标识符,我不确定如何。所有谷歌搜索都说要这样做:

$bcdStore=gwmi -name root\wmi -list bcdstore -enableall
$bcdStore|gm
$result=$bcdStore.OpenStore("") # can also use explicit file name.
$store=$result.Store

但是我知道如何使用商店,这看起来有点太复杂了。我的意思是应该有一个更简单的方法......不是吗?

2 个答案:

答案 0 :(得分:5)

我不知道如何使用WMI,但您可以将bcdeditSelect-String结合使用:

$otherboot = bcdedit /enum |
  Select-String "path" -Context 2,0 |
  ForEach-Object { $_.Context.PreContext[0] -replace '^identifier +' } |
  Where-Object { $_ -ne "{current}" }

<强>解释

bcdedit /enum的输出大致如下:

Windows Boot Manager
--------------------
identifier              {bootmgr}
device                  partition=\Device\HarddiskVolume1
description             Windows Boot Manager
locale                  en-US
...

Windows Boot Loader
-------------------
identifier              {current}
device                  partition=C:
path                    \Windows\system32\winload.exe
description             Windows 7
locale                  en-US
...

Windows Boot Loader
-------------------
identifier              {e0610d98-e116-11e1-8aa3-e57ee342122d}
device                  partition=C:
path                    \Windows\system32\winload.exe
description             DebugEntry
locale                  en-US
...

此输出的相关部分是Windows Boot Loader部分,与Windows Boot Manager部分不同 - 具有path记录。因此,我们可以使用此记录仅选择Windows Boot Loader部分:

Select-String "path"

由于identifier记录在path记录之前是2行,我们需要2行PreContext(并且没有PostContext):

Select-String "path" -Context 2,0

现在我们从bcdedit /enum

的输出中选择了以下两个块
identifier              {current}
device                  partition=C:
path                    \Windows\system32\winload.exe
identifier              {e0610d98-e116-11e1-8aa3-e57ee342122d}
device                  partition=C:
path                    \Windows\system32\winload.exe

由于我们只对PreContext的第一行感兴趣,因此我们使用ForEach-Object循环选择这两行:

ForEach-Object { $_.Context.PreContext[0] }

将两个块减少到:

identifier              {current}
identifier              {e0610d98-e116-11e1-8aa3-e57ee342122d}

我们通过字符串替换删除类别(identifier):

ForEach-Object { $_.Context.PreContext[0] -replace '^identifier +' }

正则表达式'^identifier +'匹配一个(子)字符串,以“identifier”开头,后跟一个或多个空格,后面用空字符串替换。在更换之后,两个块被简化为:

{current}
{e0610d98-e116-11e1-8aa3-e57ee342122d}

所以现在我们只需要过滤掉包含{current}的块,剩下的是另一个启动记录的标识符:

Where-Object { $_ -ne "{current}" }

此后,变量$otherboot包含非当前引导记录的标识符。

答案 1 :(得分:0)

我知道这不是一个完整的答案,但它可能足以让你开始。下面的代码输出BCD知道的所有操作系统的显示名称。

$cxOptions= new-object System.Management.ConnectionOptions
$cxOptions.Impersonation=[System.Management.ImpersonationLevel]::Impersonate
$cxOptions.EnablePrivileges=$true

$mgmtScope=new-object System.Management.ManagementScope -ArgumentList "root\WMI",$cxOptions
$mgmtPath=new-object System.Management.ManagementPath -ArgumentList 'root\WMI:BcdObject.Id="{9dea862c-5cdd-4e70-acc1-f32b344d4795}",StoreFilePath=""'
$mgmtObject=new-object System.Management.ManagementObject -ArgumentList $mgmtScope,$mgmtPath,$null

# Determine what elements exist in the object and output their value in HEX format
#$mgmtObject.EnumerateElementTypes().types | % { "{0:X0}" -f $_ }

$objBCD=$mgmtObject.GetElement(0x24000001)
$objElements=$objBCD.GetPropertyValue("Element")

$strOldID="{9dea862c-5cdd-4e70-acc1-f32b344d4795}"
for ($i=0; $i -lt $objElements.Ids.Count; $i++) {
  $mgmtPath.Path=$mgmtPath.Path.Replace($strOldID,$objElements.Ids[$i])
  $strOldID=$objElements.Ids[$i]
  $objBCDId=new-object System.Management.ManagementObject -ArgumentList $mgmtScope,$mgmtPath,$null
  $strOS=$objBCDId.GetElement(0x12000004)
  $strOS.Element.String
}