5

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

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

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

4

3 回答 3

7

我不知道使用 WMI 的方法,但您可以bcdedit结合使用Select-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 ManagerpathWindows Boot Loader

Select-String "path"

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

Select-String "path" -Context 2,0

现在我们从输出中选择了以下两个块bcdedit /enum

标识符 {当前}
设备分区=C:
路径 \Windows\system32\winload.exe
标识符 {e0610d98-e116-11e1-8aa3-e57ee342122d}
设备分区=C:
路径 \Windows\system32\winload.exe

因为我们只对第一行感兴趣,所以我们使用循环PreContext选择这两行:ForEach-Object

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

这将两个块减少为:

标识符 {当前}
标识符 {e0610d98-e116-11e1-8aa3-e57ee342122d}

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

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

正则表达式'^identifier +'匹配以单词“identifier”开头的(子)字符串,后跟一个或多个空格,替换为空字符串。在这个替换之后,两个块减少到这个:

{当前的}
{e0610d98-e116-11e1-8aa3-e57ee342122d}

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

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

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

于 2013-06-03T19:51:10.777 回答
1

团队!

我写了 BCDEdit 解析器。我认为这将是有用的。

$Configs   = @() #Array contains the parsed objects
$NameArray = @()

$Pattern = '^(?<name>[a-z]*)?\s*(?<value>.*)?$'
$enum    = bcdedit /enum

foreach ($item in $enum ){
    if ( $item.trim() ){
        $res = [regex]::matches( $item, $pattern )
        if ( $res ){
            $Value = $res[0].Groups['value'].value 
            $Name  = $res[0].Groups['name'].value
            if ( $Value ){
                if ( $Name ){
                    $PSO = [PSCustomObject]@{
                        Name  = $Name
                        Value = $Value
                    }
                    $NameArray += $PSO
                }
                Else {
                    if ( $NameArray.count ){
                        ( $NameArray | Select-Object -last 1 ).Value += "; $Value"
                    }
                }
            }            
        }
    }
    Else {
        if ( $NameArray ){
            $Configs  += ,$NameArray
            $NameArray = @()
        }
    }
}

#Show results
foreach ( $item in $Configs){
    $item | Format-Table
}

于 2021-10-11T18:13:19.150 回答
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
}
于 2015-08-31T12:23:31.967 回答