65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 PowerShell 修改 Windows BCD

starIconstarIconstarIconstarIconstarIcon

5.00/5 (6投票s)

2014年11月2日

CPOL

10分钟阅读

viewsIcon

50077

在 PowerShell 中处理 Windows BCD 存储

背景

由于 BCD 的复杂性,本文将不会深入介绍 BCD。本文旨在演示管理 BCD 存储区的经过测试的技术。对于本文,所有 BCD 操作都在本地进行。此外,BCD 的 WMI 提供程序需要管理员权限。

警告

不当地修改系统 BCD 存储区可能导致操作系统无法启动。尽管本文的代码已将 bcd.mof 文件完全转换为 PowerShell 函数,但并非所有方法都会涵盖,本文未涵盖的方法也未经广泛测试。在使用本文未描述的方法之前,请查阅 Microsoft 文档。Microsoft 和作者对本代码的使用方式概不负责。

代码更新

为解决 COM 错误,增加了对 PowerShell 5 的支持。

访问 BCD 存储区

本文将使用 WbemScripting.SWbemLocator 对象来访问 BCD 提供程序。在并排比较中,使用 System.Management 命名空间的 C# 应用程序和使用 WbemScripting 的 PowerShell 脚本使用相同的资源:wmiprvsewmiutilswbemsvcwbemcomn2wbemproxbcdprovbcdsrv(以及其他)。对于 PowerShell,使用 WMI 脚本 API 更为容易。通过仅使用 COM 对象,只需几个(简单的)函数即可访问 BCD WMI 提供程序。

获取 staticBcdStore 的实例

function Get-StaticBcdStore {
    $SWbemLocator = New-Object -ComObject WbemScripting.SWbemLocator
    $wmi = $SWbemLocator.ConnectServer(".","root\wmi")
    $wmi.Get("BcdStore")
}

四个 COM 辅助函数

访问方法参数

function New-InParameter {
Param([Parameter(Position=0)]$Method, [Parameter(ValueFromPipeLine=$true)]$Object)
    $Object.Methods_.Item($Method).InParameters.SpawnInstance_()
}

访问属性

function Get-PropertyValue {
Param([Parameter(Position=0)]$Property, [Parameter(ValueFromPipeLine=$true)]$Object)
    $Object.Properties_.Item($Property).Value
}
function Set-PropertyValue {
Param([Parameter(Position=0)]$Property, [Parameter(Position=1)]$Value, 
      [Parameter(ValueFromPipeLine=$true)]$Object)
    $Object.Properties_.Item($Property).Value=$Value
}

方法执行和参数返回值

function Invoke-Method {
Param([Parameter(Position=0)]$Method, [Parameter(Position=1)]$ParameterNames, 
      [Parameter(Position=2)]$ParameterValues,
    [Parameter(ValueFromPipeLine=$true)]$Object)
    if($ParameterNames -eq $null -or $ParameterValues -eq $null) {
        # If the method has required parameters: "The remote procedure call failed."
        $Object.ExecMethod_($Method)
    }
    else {
        $in = $Object.Methods_.Item($Method).InParameters.SpawnInstance_()
        if($ParameterNames.GetType() -eq [System.String]) {
            $prop = $in.Properties_.Item($ParameterNames)
            $prop.GetType().InvokeMember("Value", 
            [System.Reflection.BindingFlags]::SetProperty,$null,$prop,@($ParameterValues))
        }
        else {
            for($i = 0; $i -lt $ParameterNames.LongLength; $i++) {
                if($ParameterValues[$i] -ne $null) {
                    $prop = $in.Properties_.Item($ParameterNames[$i])
                    if($ParameterValues[$i] -is [array]) {
                        $prop.GetType().InvokeMember("Value", 
                        [System.Reflection.BindingFlags]::SetProperty,
                         $null,$prop,@(,$ParameterValues[$i]))
                    } else {
                        $prop.GetType().InvokeMember("Value", 
                        [System.Reflection.BindingFlags]::SetProperty,
                         $null,$prop,@($ParameterValues[$i]))
                    }
                }
            }
        }

        $Object.ExecMethod_($Method, $in)
    }
}

实现 BCD WMI 方法

BCD 提供程序公开的所有方法都可以在 bcd.mof(Managed Object Format)文件中找到。对于本文,以及提供的 PowerShell 代码,它们根据对象关系分为三个主要类别:仅与 BcdStore 相关的函数和属性、仅与 BcdObject 相关的函数和属性,以及与 BcdElements 相关且包含共享属性的函数和属性。在实现这些方法时,任何 out 参数都用作函数的返回值,否则,返回值将是一个布尔值,指示操作的成功或失败。

处理 BCD 存储区

要访问存储区并检索项目,将使用以下方法

function Open-Store {
    Param(
        [Parameter(Position=0)][string]$File="",
        [Parameter(Mandatory=$true, ValueFromPipeLine=$true)]$BcdStore
    )
    $BcdStore | Invoke-Method "OpenStore" "File" $File | Get-PropertyValue "Store"
}
function Open-Object {
    Param(
        [Parameter(Position=0)][string]$Id,
        [Parameter(Mandatory=$true, ValueFromPipeLine=$true)]$BcdStore
    )
    $BcdStore | Invoke-Method "OpenObject" "Id" $Id | Get-PropertyValue "Object"
}
function Enumerate-Objects {
    Param(
        [Parameter(Position=0)][uint32]$Type,
        [Parameter(Mandatory=$true, ValueFromPipeLine=$true)]$BcdStore
    )
    $BcdStore | Invoke-Method "EnumerateObjects" "Type" $Type | Get-PropertyValue "Objects"
}

要打开 BCD 存储区,必须指定 BCD 文件名。空字符串表示系统存储区。获取 BCD 对象需要对象的 GUID 标识。枚举 BCD 对象需要一个对象类型。

$bootmanager = Get-StaticBcdStore | Open-Store -file "" | 
               Open-Object "{9dea862c-5cdd-4e70-acc1-f32b344d4795}"
$bootmanager.Properties_

在此示例中,使用 Windows 引导管理器(Windows Boot Manager)的已知 GUID 从系统存储区获取引导管理器,并输出 COM 属性。结果仅为 BcdObject 属性:Id(即已知 GUID)、StoreFilePath(因为在系统存储区中,所以为空)和 Type(即 0x10100002)。

在上一个示例中,通过使用已知 GUID 显式检索了引导管理器。但是;也可以通过其类型来检索此元素。

$bootmanagers = Get-StaticBcdStore | Open-Store "" | 
                Enumerate-Objects ([uint32]"0x10100002")
$bootmanagers[0].Properties_

$bootmanagers = Get-StaticBcdStore | Open-Store "" | Enumerate-Objects ([uint32]"0x10000002")
$bootmanagers[0].Properties_

这些示例指出了按类型定义枚举对象的能力。在第二个示例中,对象类型被泛化,以指示任何应用程序代码为 Windows 引导管理器的应用程序类型对象。

要创建 BCD 存储区和 BCD 对象,将使用以下两个方法

function Create-Store {
    Param(
        [Parameter(Position=0)][string]$File,
        [Parameter(Mandatory=$true, ValueFromPipeLine=$true)]$BcdStore
    )
    $BcdStore | Invoke-Method "CreateStore" 
                "File" $File | Get-PropertyValue "Store"
}
function Create-Object {
    Param(
        [Parameter(Position=0)][uint32]$Type,
        [Parameter(Position=1)][string]$Id,  
        [Parameter(Mandatory=$true, ValueFromPipeLine=$true)]$BcdStore
    )
    $BcdStore | Invoke-Method "CreateObject" 
    "Id","Type" $Id,$Type | Get-PropertyValue "Object"
}

OpenStore 方法类似,BcdStoreCreateStore 方法需要一个文件名。在 BCD 存储区中创建对象需要一个类型和一个可选的 GUID 或已知 GUID。

Get-StaticBcdStore | Create-Store "$env:TEMP\BCD-Demo" `
    | Create-Object ([uint32]"0x10100001") 
    "{a5a30fa2-3d06-4e9f-b5f4-a01df9d1fcba}"

在此示例中,使用固件引导管理器(Firmware Boot Manager)的已知 GUID 和固件引导管理器(Firmware Boot Manager)的对象类型来创建:固件引导管理器。Id 参数是可选的。要创建新对象,只需传递对象类型,对象的 Id 将由提供程序生成的 GUID 填充。但是,许多对象,如这个固件引导管理器,只能通过已知的 GUID 和类型组合来创建。

处理 BCD 对象

设置元素需要 BcdObject 提供的。这些方法共有的特点是使用 Type 来定义要操作的对象元素。Microsoft 的 MSDN 提供了相当完整的(尽管不总是准确的)枚举列表。我的意思是,一些枚举值可能被定义为特定类型,但它们实际上不是该类型,而其他缺失的枚举值——尽管它们可以用现有值替代。

以下方法用于从 BcdObject 中检索元素数据

function Enumerate-Elements {
    Param([Parameter(Position=0, ValueFromPipeLine=$true)]$BcdObject)
    $BcdObject | Invoke-Method "EnumerateElements" | Get-PropertyValue "Elements"
}
function Get-Element {
        Param([Parameter(Position=0)][uint32]$Type,
        [Parameter(ValueFromPipeLine=$true)]$BcdObject
    )
    $BcdObject | Invoke-Method "GetElement" 
    "Type" $Type | Get-PropertyValue "Element"
}
function Enumerate-ElementTypes {
    Param([Parameter(Position=0, ValueFromPipeLine=$true)]$BcdObject)
    $BcdObject | Invoke-Method "EnumerateElementTypes" | Get-PropertyValue "Types"
}

要获取元素、元素类型和值的列表,只需执行以下操作

$bootmanager = Get-StaticBcdStore | Open-Store -file "" | 
Open-Object "{9dea862c-5cdd-4e70-acc1-f32b344d4795}"
$bootmanager | Enumerate-ElementTypes | % {
    (Get-Element -Type $_ -BcdObject $bootmanager).Properties_
}

至于设置元素数据,以下方法将在后面演示,但名称如 SetBooleanElementSetStringElement,它们不言自明。

function Set-StringElement {
    Param(
        [Parameter(Position=0)][uint32]$Type,
        [Parameter(Position=1)][string]$String,
        [Parameter(ValueFromPipeLine=$true)]$BcdObject
    )
    $BcdObject | Invoke-Method "SetStringElement" 
    "Type","String" $Type,$String | Get-PropertyValue "ReturnValue"
}
function Set-BooleanElement {
    Param(
        [Parameter(Position=0)][uint32]$Type,
        [Parameter(Position=1)][bool]$Boolean,
        [Parameter(ValueFromPipeLine=$true)]$BcdObject
    )
    $BcdObject | Invoke-Method "SetBooleanElement" 
    "Type","Boolean" $Type,$Boolean | Get-PropertyValue "ReturnValue"
}
function Set-IntegerElement {
    Param(
        [Parameter(Position=0)][uint32]$Type,
        [Parameter(Position=1)]$Integer,
        [Parameter(ValueFromPipeLine=$true)]$BcdObject
    )
    $BcdObject | Invoke-Method "SetIntegerElement" 
    "Type","Integer" $Type,$Integer | Get-PropertyValue "ReturnValue"
}
function Set-ObjectElement {
    Param(
        [Parameter(Position=0)][uint32]$Type,
        [Parameter(Position=1)][string]$Id,
        [Parameter(ValueFromPipeLine=$true)]$BcdObject
    )
    $BcdObject | Invoke-Method "SetObjectElement" 
    "Type","Id" $Type,$Id | Get-PropertyValue "ReturnValue"
}

一些方法将接受值数组,应使用 @() 传递这些值。

function Set-ObjectListElement {
    Param(
        [Parameter(Position=0)][uint32]$Type,
        [Parameter(Position=1)]$Ids,
        [Parameter(ValueFromPipeLine=$true)]$BcdObject
    )
    $BcdObject | Invoke-Method "SetObjectListElement" 
    "Type","Ids" $Type,$Ids | Get-PropertyValue "ReturnValue"
}
function Set-IntegerListElement {
    Param(
        [Parameter(Position=0)][uint32]$Type,
        [Parameter(Position=1)]$Integers,
        [Parameter(ValueFromPipeLine=$true)]$BcdObject
    )
    $BcdObject | Invoke-Method "SetIntegerListElement" 
    "Type","Integers" $Type,$Integers | Get-PropertyValue "ReturnValue"
}

设置设备数据要复杂得多,也将在后面演示

function Set-FileDeviceElement {
    Param(
        [Parameter(Position=0)][uint32]$Type,
        [Parameter(Position=1)][int]$DeviceType,
        [Parameter(Position=2)][string]$AdditionalOptions,
        [Parameter(Position=3)][string]$Path,
        [Parameter(Position=4)][uint32]$ParentDeviceType,
        [Parameter(Position=5)][string]$ParentAdditionalOptions,
        [Parameter(Position=6)][string]$ParentPath,
        [Parameter(ValueFromPipeLine=$true)]$BcdObject
    )
    $parameterNames = "Type","DeviceType","AdditionalOptions",
    "Path","ParentDeviceType","ParentAdditionalOptions","ParentPath"
    $parameterValues = $Type,$DeviceType,$AdditionalOptions,
    $Path,$ParentDeviceType,$ParentAdditionalOptions,$ParentPath
    $BcdObject | Invoke-Method "SetFileDeviceElement" 
    $parameterNames $parameterValues | Get-PropertyValue "ReturnValue"
}
function Set-PartitionDeviceElement {
    Param(
        [Parameter(Position=0)][uint32]$Type,
        [Parameter(Position=1)][int]$DeviceType,
        [Parameter(Position=2)][string]$AdditionalOptions,
        [Parameter(Position=3)][string]$Path,
        [Parameter(ValueFromPipeLine=$true)]$BcdObject
    )
    $parameterNames = "Type","DeviceType",
    "AdditionalOptions","Path"
    $parameterValues = $Type,$DeviceType,$AdditionalOptions,$Path
    $BcdObject | Invoke-Method "SetPartitionDeviceElement" 
    $parameterNames $parameterValues | Get-PropertyValue "ReturnValue"
}

BcdObject 提供了更多方法,并在本文后面的代码中包含,尽管本文未涵盖。

处理 BCD 元素

最后一个介绍 BCD 方法的部分将介绍 BCD 对象的实际元素。在前面的部分中,我们介绍了如何使用 BcdStore 对象来打开和创建对象,并简要提及了如何使用 BcdObject 来设置元素数据。要从元素中获取特定信息,我们必须访问元素的属性。string 元素有一个 String 属性,布尔元素有一个 Boolean 属性,依此类推。

function Get-String {
Param([Parameter(Mandatory=$true, Position=0, ValueFromPipeLine=$true)]$BcdStringElement)
    Get-PropertyValue "String" -Object $BcdStringElement
}
function Get-Integer {
Param([Parameter(Mandatory=$true, Position=0, ValueFromPipeLine=$true)]$BcdIntegerElement)
    Get-PropertyValue "Integer" -Object $BcdIntegerElement
}
function Get-Boolean {
Param([Parameter(Mandatory=$true, Position=0, ValueFromPipeLine=$true)]$BcdBooleanElement)
    Get-PropertyValue "Boolean" -Object $BcdBooleanElement
}

对于对象列表

function Get-Integers {
Param([Parameter(Mandatory=$true, Position=0, ValueFromPipeLine=$true)]$BcdIntegerListElement)
    Get-PropertyValue "Integers" -Object $BcdIntegerListElement
}
function Get-Ids {
Param([Parameter(Mandatory=$true, Position=0, ValueFromPipeLine=$true)]$BcdObjectListElement)
    Get-PropertyValue "Ids" -Object $BcdObjectListElement
}

对于设备对象

function Get-Device {
Param([Parameter(Mandatory=$true, Position=0, ValueFromPipeLine=$true)]$BcdDeviceElement)
    $BcdDeviceElement | Get-PropertyValue "Device"
}

这将是获取 BCD 存储区数据的最后一个演示。(压轴好戏:获取设备数据。)

$mem = Get-StaticBcdStore | Open-Store "" | 
       Open-Object "{b2721d73-1db4-4c62-bf78-c548a880142d}"
$dev = $mem | Get-Element 
       -Type ([BcdLibraryElementTypes]::Device_ApplicationDevice) | Get-Device
$dev.Properties_

此示例获取 Windows 内存测试程序(Windows Memory Tester)并检索设备数据。此方法对于通过代码评估设置各种设备元素的属性非常有用。

最后,重头戏

现在…本文的最终目标是提供从 PowerShell 修改 BCD 存储区的实际示例。

从头开始构建 BCD 存储区

对于第一个演示,将使用实时系统存储区的 bcdedit 输出在代码中生成新的 BCD 存储区。生成的 BCD 存储区将创建一个已清理、重新格式化并在部署场景中重新映像的驱动器上。bcdedit 的大部分输出已按对象依赖关系重新排序。枚举器和已知 GUID 变量在本文末尾的代码中提供。

. ("$PSScriptRoot\PowershellBcd.ps1")
Get-StaticBcdStore | Create-Store -File "$env:TEMP\BCD-TEMP" | Out-Null
$bcdFile = "S:\boot\BCD"
if(Test-Path $bcdFile) {
    Remove-Item -Path $bcdFile | Out-Null
}
$sDrive = Get-DosDevice "S:"
# Windows OS (will be C after reboot)
$cDrive = Get-DosDevice "W:"
$BcdStore = Get-StaticBcdStore | Create-Store -File $bcdFile
$BcdStore | Import-Store "$env:TEMP\BCD-TEMP" | Out-Null

*BCD WMI 提供程序似乎没有实现 QueryDosDevice——与 bcdedit 不同,在设置 Device 属性时,它不接受卷标。此外,虽然从头开始构建 BCD 存储区会生成一个功能齐全的存储区,并且操作系统能够正常启动、休眠和恢复,但启动到 WinRE 总是会导致 BCD 存储区重建。要使存储区正常工作,必须导入一个“虚拟”存储区。这会生成一个功能正常的 BCD 存储区。(此解决方案可在此链接找到。)

EMS 设置
------------
标识符 {0ce4991b-e6b3-4b16-b23c-5e0d9250e5d9}
bootems
$BcdStore | Create-Object -Id $emssettings -Type ([uint32]"0x20100000") | `
    Set-BooleanElement ([BcdLibraryElementTypes]::Boolean_EmsEnabled) 1 | Out-Null
调试器设置
-----------------
标识符 {4636856e-540f-4170-a130-a84776f4c654}
debugtype 串口
debugport 1
baudrate 115200
$debugger = $BcdStore | Create-Object -Id $dbgsettings -Type ([uint32]"0x20100000")
$debugger | Set-IntegerElement 
            ([BcdLibraryElementTypes]::Integer_DebuggerType) 0 | Out-Null
$debugger | Set-IntegerElement 
            ([BcdLibraryElementTypes]::Integer_SerialDebuggerPort) 1 | Out-Null
$debugger | Set-IntegerElement 
            ([BcdLibraryElementTypes]::Integer_SerialDebuggerBaudRate) 115200 | Out-Null
RAM 缺陷
-----------
标识符 {5189b25c-5558-4bf2-bca4-289b11bd29e2}
$BcdStore | Create-Object -Id $badmemory -Type ([uint32]"0x20100000") | Out-Null
全局设置
---------------
标识符 {7ea2e1ac-2e61-4728-aaa3-896d9d0a9f0e}
inherit {4636856e-540f-4170-a130-a84776f4c654}
  {0ce4991b-e6b3-4b16-b23c-5e0d9250e5d9}
  {5189b25c-5558-4bf2-bca4-289b11bd29e2}
$global = $BcdStore | Create-Object -Id $globalsettings -Type ([uint32]"0x20100000") | `
    Set-ObjectListElement ([BcdLibraryElementTypes]::ObjectList_InheritedObjects) `
    @($dbgsettings,$emssettings,$badmemory) | Out-Null 
恢复加载程序设置
----------------------
标识符 {1afa9c49-16ab-4a5c-901b-212802da9460}
inherit {7ea2e1ac-2e61-4728-aaa3-896d9d0a9f0e}
$BcdStore | Create-Object -Id $resumeloadersettings -Type ([uint32]"0x20200004") | `
        Set-ObjectListElement ([BcdLibraryElementTypes]::ObjectList_InheritedObjects) 
        @($globalsettings) | Out-Null
Hypervisor 设置
-------------------
标识符 {7ff607e0-4395-11db-b0de-0800200c9a66}
hypervisordebugtype 串口
hypervisordebugport 1
hypervisorbaudrate 115200
$hypervisor = $BcdStore | Create-Object 
              -Id $hypervisorsettings -Type ([uint32]"0x20200003")
$hypervisor | Set-IntegerElement 
              ([BcdOSLoaderElementTypes]::Integer_HypervisorDebuggerType) 0 | Out-Null
$hypervisor | Set-IntegerElement 
              ([BcdOSLoaderElementTypes]::Integer_HypervisorDebuggerPortNumber) 1 | Out-Null
$hypervisor | Set-IntegerElement 
              ([BcdOSLoaderElementTypes]::Integer_HypervisorDebuggerBaudrate) 115200 | Out-Null
引导加载程序设置
--------------------
标识符 {6efb52bf-1766-41db-a6b3-0ee5eff72bd7}
inherit {7ea2e1ac-2e61-4728-aaa3-896d9d0a9f0e}
  {7ff607e0-4395-11db-b0de-0800200c9a66}
$BcdStore | Create-Object -Id $bootloadersettings -Type ([uint32]"0x20200003") | `
    Set-ObjectListElement ([BcdLibraryElementTypes]::ObjectList_InheritedObjects) 
    @($globalsettings,$hypervisorsettings) | Out-Null
Windows 内存测试程序
---------------------
标识符 {b2721d73-1db4-4c62-bf78-c548a880142d}
device partition=S
路径 \boot\memtest.exe
description Windows 内存诊断
locale en-US
inherit {7ea2e1ac-2e61-4728-aaa3-896d9d0a9f0e}
badmemoryaccess
$memorytester = $BcdStore | Create-Object -Id $memdiag 
                -Type ([uint32]"0x10200005")
$memorytester | Set-PartitionDeviceElement 
([BcdLibraryElementTypes]::Device_ApplicationDevice) 2 "" $sDrive | Out-Null
$memorytester | Set-StringElement 
([BcdLibraryElementTypes]::String_ApplicationPath) "\boot\memtest.exe" | Out-Null
$memorytester | Set-StringElement 
([BcdLibraryElementTypes]::String_Description) "Windows Memory Diagnostic" | Out-Null
$memorytester | Set-StringElement 
([BcdLibraryElementTypes]::String_PreferredLocale) "en-US" | Out-Null
$memorytester | Set-ObjectListElement 
([BcdLibraryElementTypes]::ObjectList_InheritedObjects) @($globalsettings) | Out-Null
$memorytester | Set-BooleanElement 
([BcdLibraryElementTypes]::Boolean_AllowBadMemoryAccess) 1 | Out-Null
从休眠中恢复
---------------------
标识符 {ebe94447-1944-11e4-95c4-dd9a4e7158f6}
device partition=C
路径 \windows\system32\winresume.exe
description Windows 恢复应用程序
locale en-US
inherit {1afa9c49-16ab-4a5c-901b-212802da9460}
filedevice partition=C
filepath \hiberfil.sys
debugoptionenabled
$hibernate = $BcdStore | Create-Object ([uint32]"0x10200004")
# Get generated GUID
$resume = $hibernate | Get-Id
$hibernate | Set-PartitionDeviceElement 
([BcdLibraryElementTypes]::Device_ApplicationDevice) 2 "" $cDrive | Out-Null
$hibernate | Set-StringElement 
([BcdLibraryElementTypes]::String_ApplicationPath) 
                           "\Windows\system32\winresume.exe" | Out-Null
$hibernate | Set-StringElement 
([BcdLibraryElementTypes]::String_Description) "Windows Resume Application" | Out-Null
$hibernate | Set-StringElement 
([BcdLibraryElementTypes]::String_PreferredLocale) "en-US" | Out-Null
$hibernate | Set-ObjectListElement 
([BcdLibraryElementTypes]::ObjectList_InheritedObjects) @($resumeloadersettings) | Out-Null
$hibernate | Set-PartitionDeviceElement 
([BcdOSLoaderElementTypes]::Device_OSDevice) 2 "" $cDrive | Out-Null
$hibernate | Set-StringElement 
([BcdOSLoaderElementTypes]::String_SystemRoot) "\hiberfil.sys" | Out-Null
$hibernate | Set-BooleanElement 
([BcdResumeElementTypes]::Boolean_DebugOptionEnabled) 0 | Out-Null
设备选项
--------------
标识符 {ebe9444a-1944-11e4-95c4-dd9a4e7158f6}
description Ramdisk 选项
ramdisksdidevice partition=S
ramdisksdipath \Recovery\WindowsRE\boot.sdi
$ramdisk = $BcdStore | Create-Object -Id $ramdiskopt -Type ([uint32]"0x30000000")
$ramdisk | Set-StringElement 
           ([BcdLibraryElementTypes]::String_Description) "Ramdisk Options" | Out-Null
$ramdisk | Set-PartitionDeviceElement 
           ([BcdDeviceObjectElementTypes]::Device_SdiDevice) 2 "" $sDrive | Out-Null
$ramdisk | Set-StringElement 
([BcdDeviceObjectElementTypes]::String_SdiPath) "\Recovery\WindowsRE\boot.sdi" | Out-Null
Windows 引导加载程序
-------------------
标识符 {ebe94449-1944-11e4-95c4-dd9a4e7158f6}
device ramdisk=[S:]\Recovery\WindowsRE\Winre.wim,{ebe9444a-1944-11e4-95c4-dd9a4e7158f6}
路径 \windows\system32\winload.exe
description Windows 恢复环境
inherit {6efb52bf-1766-41db-a6b3-0ee5eff72bd7}
osdevice ramdisk=[S:]\Recovery\WindowsRE\Winre.wim,{ebe9444a-1944-11e4-95c4-dd9a4e7158f6}
systemroot \windows
nx OptIn
winpe
custom:46000010
$winre = $BcdStore | Create-Object ([uint32]"0x10200003")
# Get Generated GUID
$reLoader = $winre | Get-Id
$winre | Set-FileDeviceElement 
         -Type ([BcdLibraryElementTypes]::Device_ApplicationDevice) -DeviceType 4 `
    -AdditionalOptions $ramdiskopt -Path "\Recovery\WindowsRE\Winre.wim" -ParentDeviceType 2 `
    -ParentAdditionalOptions "" -ParentPath $sDrive | Out-Null
$winre | Set-StringElement ([BcdLibraryElementTypes]::String_ApplicationPath) 
         "\Windows\system32\winload.exe" | Out-Null
$winre | Set-StringElement ([BcdLibraryElementTypes]::String_Description) 
         "Windows Recovery Environment" | Out-Null
$winre | Set-ObjectListElement ([BcdLibraryElementTypes]::ObjectList_InheritedObjects) 
         @($bootloadersettings) | Out-Null
$winre | Set-FileDeviceElement -Type ([BcdOSLoaderElementTypes]::Device_OSDevice) 
    -DeviceType 4 -AdditionalOptions $ramdiskopt  `
    -Path "\Recovery\WindowsRE\Winre.wim" -ParentDeviceType 2 `
    -ParentAdditionalOptions "" -ParentPath $sDrive | Out-Null
$winre | Set-StringElement ([BcdOSLoaderElementTypes]::String_SystemRoot) 
         "\Windows" | Out-Null
$winre | Set-IntegerElement ([BcdOSLoaderElementTypes]::Integer_NxPolicy) 0 | Out-Null
$winre | Set-BooleanElement ([BcdOSLoaderElementTypes]::Boolean_WinPEMode) 1 | Out-Null
$winre | Set-BooleanElement ([uint32]"0x46000010") 1 | Out-Null
Windows 引导加载程序
-------------------
标识符 {ebe94448-1944-11e4-95c4-dd9a4e7158f6}
device partition=C
路径 \windows\system32\winload.exe
description Windows 7
locale en-US
inherit {6efb52bf-1766-41db-a6b3-0ee5eff72bd7}
recoverysequence {ebe94449-1944-11e4-95c4-dd9a4e7158f6}
recoveryenabled
osdevice partition=C
systemroot \windows
resumeobject {ebe94447-1944-11e4-95c4-dd9a4e7158f6}
nx OptIn
$loader = $BcdStore | Create-Object ([uint32]"0x10200003")
# Get generated GUID
$osLoader = $loader | Get-Id
$loader | Set-PartitionDeviceElement 
([BcdLibraryElementTypes]::Device_ApplicationDevice) 2 "" $cDrive | Out-Null
$loader | Set-StringElement 
([BcdLibraryElementTypes]::String_ApplicationPath) 
            "\Windows\system32\winload.exe" | Out-Null
$loader | Set-StringElement 
([BcdLibraryElementTypes]::String_Description) "Windows 7" | Out-Null
$loader | Set-StringElement 
([BcdLibraryElementTypes]::String_PreferredLocale) "en-US" | Out-Null
$loader | Set-ObjectListElement 
([BcdLibraryElementTypes]::ObjectList_InheritedObjects) @($bootloadersettings) | Out-Null
$loader | Set-ObjectListElement 
([BcdLibraryElementTypes]::ObjectList_RecoverySequence) @($reLoader) | Out-Null
$loader | Set-BooleanElement 
([BcdLibraryElementTypes]::Boolean_AutoRecoveryEnabled) 1 | Out-Null
$loader | Set-PartitionDeviceElement 
([BcdOSLoaderElementTypes]::Device_OSDevice) 2 "" $cDrive | Out-Null
$loader | Set-StringElement 
([BcdOSLoaderElementTypes]::String_SystemRoot) "\Windows" | Out-Null
$loader | Set-ObjectElement 
([BcdOSLoaderElementTypes]::Object_AssociatedResumeObject) $resume | Out-Null
$loader | Set-IntegerElement 
([BcdOSLoaderElementTypes]::Integer_NxPolicy) 0 | Out-Null
Windows 引导管理器
--------------------
标识符 {9dea862c-5cdd-4e70-acc1-f32b344d4795}
device partition=S
description Windows 引导管理器
locale en-US
inherit {7ea2e1ac-2e61-4728-aaa3-896d9d0a9f0e}
默认 {ebe94448-1944-11e4-95c4-dd9a4e7158f6}
resumeobject {ebe94447-1944-11e4-95c4-dd9a4e7158f6}
displayorder {ebe94448-1944-11e4-95c4-dd9a4e7158f6}
toolsdisplayorder {b2721d73-1db4-4c62-bf78-c548a880142d}
timeout 30
$bootManager = $BcdStore | Create-Object -Id $bootmgr -Type ([uint32]"0x10100002")
$bootManager | Set-PartitionDeviceElement 
([BcdLibraryElementTypes]::Device_ApplicationDevice) 2 "" $sDrive | Out-Null
$bootManager | Set-StringElement 
([BcdLibraryElementTypes]::String_Description) "Windows Boot Manager" | Out-Null
$bootManager | Set-StringElement 
([BcdLibraryElementTypes]::String_PreferredLocale) "en-US" | Out-Null
$bootManager | Set-ObjectListElement 
([BcdLibraryElementTypes]::ObjectList_InheritedObjects) @($globalsettings) | Out-Null
$bootManager | Set-ObjectElement 
([BcdBootMgrElementTypes]::Object_DefaultObject) $osLoader | Out-Null
$bootManager | Set-ObjectElement 
([BcdOSLoaderElementTypes]::Object_AssociatedResumeObject) $resume | Out-Null
$bootManager | Set-ObjectListElement 
([BcdBootMgrElementTypes]::ObjectList_DisplayOrder) @($osLoader) | Out-Null
$bootManager | Set-ObjectListElement 
([BcdBootMgrElementTypes]::ObjectList_ToolsDisplayOrder) @($memdiag) | Out-Null
$bootManager | Set-IntegerElement 
               ([BcdBootMgrElementTypes]::Integer_Timeout) 30 | Out-Null

更新 USB BCD 存储区

对于第二个演示,将一个 WinPE 文件添加到现有的 WinPE USB 中。除了添加 Windows 引导加载程序外,还有必要更新 ems(紧急管理服务)设置以显示启动菜单(如果尚未启用)。由于 BCD 存储区已有一个 Ramdisk Option,因此不需要新的;但是,有必要获取现有 Device Option 的 Id。最后,在添加新的引导加载程序后,需要更新 Windows 引导管理器的显示顺序以包含新的引导加载程序。

$storeFile = "BCD file"
$wimFile = "\sources\boot2.wim"

$bcdStore = Get-StaticBcdStore | Open-Store $storeFile

# Ramdisk Options
$devices = $bcdStore | Enumerate-Objects ([uint32]"0x30000000")
if($devices.Count -gt 1) {
    Write-Host "Not prepared for this..."
    return
}
else {
    if(($devices | Get-Element 
    ([BcdDeviceObjectElementTypes]::String_SdiPath)) -ne $null) {
        $id = $devices | Get-Id
    }
}

if([String]::IsNullOrEmpty($id)) {
    Write-Host "Missing Ramdisk Option"
    return
}

$winre = $BcdStore | Create-Object ([uint32]"0x10200003")

$winre | Set-FileDeviceElement 
         -Type ([BcdLibraryElementTypes]::Device_ApplicationDevice) 
         -DeviceType ([DeviceTypes]::RamdiskDevice) `
    -AdditionalOptions $id -Path $wimFile -ParentDeviceType 1 `
    -ParentAdditionalOptions "" -ParentPath "" | Out-Null
$winre | Set-StringElement ([BcdLibraryElementTypes]::String_ApplicationPath) 
         "\Windows\system32\winload.exe" | Out-Null
$winre | Set-StringElement 
([BcdLibraryElementTypes]::String_Description) "An additional WinPE" | Out-Null
$winre | Set-ObjectListElement 
([BcdLibraryElementTypes]::ObjectList_InheritedObjects) @($bootloadersettings) | Out-Null
$winre | Set-FileDeviceElement 
         -Type ([BcdOSLoaderElementTypes]::Device_OSDevice) -DeviceType 4 `
    -AdditionalOptions $id -Path $wimFile -ParentDeviceType 1 `
    -ParentAdditionalOptions "" -ParentPath "" | Out-Null
$winre | Set-StringElement 
         ([BcdOSLoaderElementTypes]::String_SystemRoot) "\Windows" | Out-Null
$winre | Set-IntegerElement ([uint32]"0x250000C2") 1 | Out-Null
$winre | Set-BooleanElement 
         ([BcdOSLoaderElementTypes]::Boolean_DetectKernelAndHal) 1 | Out-Null
$winre | Set-BooleanElement ([BcdOSLoaderElementTypes]::Boolean_WinPEMode) 1 | Out-Null

# Windows Boot Loader
$loader = $bcdStore | Enumerate-Objects ([uint32]"0x10200003")

$values = @()

$loader | % {
    $values += ($_ | Get-Id)
    # update ems
    $_ | Set-BooleanElement 
         ([BcdOSLoaderElementTypes]::Boolean_EmsEnabled) 1 | Out-Null
}

# enable ems
$BcdStore | Open-Object $emssettings | 
Set-BooleanElement ([BcdLibraryElementTypes]::Boolean_EmsEnabled) 1 | Out-Null

$bcdStore | Open-Object $bootmgr | Set-ObjectListElement 
-Type ([BcdBootMgrElementTypes]::ObjectList_DisplayOrder) -Ids $values

*引导加载程序和引导管理器出现的 Boolean_EmsEnabled 不相同。

仅为好玩——构建 BCD 模板

最后一个演示将重新创建位于 system32\config 的 BCD-Template。这将展示一些标准 BCD 存储区中未定义的 BCD 对象。

一些重复的操作已简化——例如,使用 Set-InheritedObjects 函数来包装 Set-ObjectListElement ([BcdLibraryElementTypes]::ObjectList_InheritedObjects)。此外,混合使用基本和详细的 bcdedit 输出,以提供更准确的演示代码结果。

EMS 设置
------------
标识符 {emssettings}
bootems
$BcdStore | Create-Object -Id $emssettings -Type ([uint32]"0x20100000") | `
    Set-BooleanElement ([BcdLibraryElementTypes]::Boolean_EmsEnabled) 1 | Out-Null
调试器设置
-----------------
标识符 {dbgsettings}
debugtype 串口
debugport 1
baudrate 115200
$debugger = $BcdStore | Create-Object -Id $dbgsettings -Type ([uint32]"0x20100000")
$debugger | Set-IntegerElement ([BcdLibraryElementTypes]::Integer_DebuggerType) 0 | Out-Null
$debugger | Set-IntegerElement 
            ([BcdLibraryElementTypes]::Integer_SerialDebuggerPort) 1 | Out-Null
$debugger | Set-IntegerElement 
            ([BcdLibraryElementTypes]::Integer_SerialDebuggerBaudRate) 115200 | Out-Null
RAM 缺陷
-----------
标识符 {badmemory}
$BcdStore | Create-Object -Id $badmemory -Type ([uint32]"0x20100000") | Out-Null
全局设置
---------------
标识符 {globalsettings}
inherit {dbgsettings}
  {emssettings}
  {badmemory}
$global = $BcdStore | Create-Object -Id $globalsettings -Type ([uint32]"0x20100000") | `
    Set-InheritedObjects @($dbgsettings,$emssettings,$badmemory) | Out-Null 
恢复加载程序设置
----------------------
标识符 {resumeloadersettings}
inherit {globalsettings}
$BcdStore | Create-Object -Id $resumeloadersettings -Type ([uint32]"0x20200004") | `
        Set-InheritedObjects -Value @($globalsettings) | Out-Null
Windows 传统操作系统加载程序
------------------------
标识符 {ntldr}
路径 \ntldr
custom:45000001 1
custom:47000005 301989892
  6
$legacy = $BcdStore | Create-Object -Id $ntldr -Type ([uint32]"0x10300006")
$legacy | Set-ApplicationPath "\ntldr" | Out-Null
$legacy | Set-IntegerElement ([uint32]"0x45000001") 1 | Out-Null
$legacy | Set-IntegerListElement ([uint32]"0x47000005") 
          @(([uint32]"0x12000004"),6) | Out-Null
Hypervisor 设置
-------------------
标识符 {hypervisorsettings}
hypervisordebugtype 串口
hypervisordebugport 1
hypervisorbaudrate 115200
$hypervisor = $BcdStore | Create-Object -Id $hypervisorsettings -Type ([uint32]"0x20200003")
$hypervisor | Set-IntegerElement 
            ([BcdOSLoaderElementTypes]::Integer_HypervisorDebuggerType) 0 | Out-Null
$hypervisor | Set-IntegerElement 
            ([BcdOSLoaderElementTypes]::Integer_HypervisorDebuggerPortNumber) 1 | Out-Null
$hypervisor | Set-IntegerElement 
            ([BcdOSLoaderElementTypes]::Integer_HypervisorDebuggerBaudrate) 115200 | Out-Null
引导加载程序设置
--------------------
标识符 {bootloadersettings}
inherit {globalsettings}
  {hypervisorsettings}
$BcdStore | Create-Object -Id $bootloadersettings -Type ([uint32]"0x20200003") | `
    Set-InheritedObjects @($globalsettings,$hypervisorsettings) | Out-Null
Windows 内存测试程序
---------------------
标识符 {memdiag}
路径 \boot\memtest.exe
locale en-US
inherit {globalsettings}
badmemoryaccess
custom:45000001 1
custom:47000005 301989892
  2
$memorytester = $BcdStore | Create-Object -Id $memdiag -Type ([uint32]"0x10200005")
$memorytester | Set-ApplicationPath "\boot\memtest.exe" | Out-Null
$memorytester | Set-PreferredLocale "en-US" | Out-Null
$memorytester | Set-InheritedObjects @($globalsettings) | Out-Null
$memorytester | Set-BooleanElement 
    ([BcdLibraryElementTypes]::Boolean_AllowBadMemoryAccess) 1 | Out-Null
$memorytester | Set-IntegerElement ([uint32]"0x45000001") 1 | Out-Null
$memorytester | Set-IntegerListElement 
([uint32]"0x47000005") @(([uint32]"0x12000004"),2) | Out-Null
从休眠中恢复
---------------------
标识符 {0c334284-9a41-4de1-99b3-a7e87e8ff07e}
description Windows 恢复应用程序
locale en-US
inherit {resumeloadersettings}
filepath \hiberfil.sys
custom:42000002 \system32\winresume.efi
custom:45000001 2
custom:46000004
$hib2 = $BcdStore | Create-Object 
-Id "{0c334284-9a41-4de1-99b3-a7e87e8ff07e}" -Type ([uint32]"0x10200004")
$hib2 | Set-Description "Windows Resume Application" | Out-Null
$hib2 | Set-PreferredLocale "en-US" | Out-Null
$hib2 | Set-InheritedObjects @($resumeloadersettings) | Out-Null
# String_HiberFilePath
$hib2 | Set-StringElement ([BcdOSLoaderElementTypes]::String_SystemRoot) 
        "\hiberfil.sys" | Out-Null
$hib2 | Set-StringElement ([uint32]"0x42000002") "\system32\winresume.efi" | Out-Null
$hib2 | Set-IntegerElement ([uint32]"0x45000001") 2 | Out-Null
$hib2 | Set-BooleanElement ([uint32]"0x46000004") 1 | Out-Null
从休眠中恢复
---------------------
标识符 {98b02a23-0674-4ce7-bdad-e0a15a8ff97b}
description Windows 恢复应用程序
locale en-US
inherit {resumeloadersettings}
filepath \hiberfil.sys
custom:42000002 \system32\winresume.exe
custom:45000001 2
custom:46000004
$hib1 = $BcdStore | Create-Object 
-Id "{98b02a23-0674-4ce7-bdad-e0a15a8ff97b}" -Type ([uint32]"0x10200004")
$hib1 | Set-Description "Windows Resume Application" | Out-Null
$hib1 | Set-PreferredLocale "en-US" | Out-Null
$hib1 | Set-InheritedObjects @($resumeloadersettings) | Out-Null
$hib1 | Set-StringElement ([BcdOSLoaderElementTypes]::String_SystemRoot) 
        "\hiberfil.sys" | Out-Null
$hib1 | Set-StringElement ([uint32]"0x42000002") "\system32\winresume.exe" | Out-Null
$hib1 | Set-IntegerElement ([uint32]"0x45000001") 2 | Out-Null
$hib1 | Set-BooleanElement ([uint32]"0x46000004") 1 | Out-Null
OS 目标模板
------------------
标识符 {a1943bbc-ea85-487c-97c7-c9ede908a38a}
locale en-US
inherit {6efb52bf-1766-41db-a6b3-0ee5eff72bd7}
systemroot \windows
resumeobject {98b02a23-0674-4ce7-bdad-e0a15a8ff97b}
nx OptIn
detecthal
custom:42000002 \system32\winload.exe
custom:45000001 2
custom:47000005 301989892
  3
$template2 = $BcdStore | Create-Object 
    -Id "{a1943bbc-ea85-487c-97c7-c9ede908a38a}" -Type ([uint32]"0x10200003")
$template2 | Set-PreferredLocale "en-US" | Out-Null
$template2 | Set-InheritedObjects @($bootloadersettings) | Out-Null
$template2 | Set-StringElement ([BcdOSLoaderElementTypes]::String_SystemRoot) 
             "\windows" | Out-Null
$template2 | Set-ObjectElement ([BcdOSLoaderElementTypes]::Object_AssociatedResumeObject) 
             "{98b02a23-0674-4ce7-bdad-e0a15a8ff97b}" | Out-Null
$template2 | Set-IntegerElement ([BcdOSLoaderElementTypes]::Integer_NxPolicy) 0 | Out-Null
$template2 | Set-BooleanElement ([BcdOSLoaderElementTypes]::Boolean_DetectKernelAndHal) 
             1 | Out-Null
$template2 | Set-BooleanElement ([BcdOSLoaderElementTypes]::Boolean_WinPEMode) 1 | Out-Null
$template2 | Set-StringElement ([uint32]"0x42000002") "\system32\winload.exe" | Out-Null
$template2 | Set-IntegerElement ([uint32]"0x45000001") 2 | Out-Null
$template2 | Set-IntegerListElement 
([uint32]"0x47000005") @(([uint32]"0x12000004"),3) | Out-Null
OS 目标模板
------------------
标识符 {b012b84d-c47c-4ed5-b722-c0c42163e569}
locale en-US
inherit {6efb52bf-1766-41db-a6b3-0ee5eff72bd7}
systemroot \windows
resumeobject {0c334284-9a41-4de1-99b3-a7e87e8ff07e}
nx OptIn
detecthal
custom:42000002 \system32\winload.efi
custom:45000001 2
custom:47000005 301989892
  3
$template1 = $BcdStore | Create-Object 
-Id "{b012b84d-c47c-4ed5-b722-c0c42163e569}" -Type ([uint32]"0x10200003")
$template1 | Set-PreferredLocale "en-US" | Out-Null
$template1 | Set-InheritedObjects @($bootloadersettings) | Out-Null
$template1 | Set-StringElement ([BcdOSLoaderElementTypes]::String_SystemRoot) 
             "\windows" | Out-Null
$template1 | Set-ObjectElement ([BcdOSLoaderElementTypes]::Object_AssociatedResumeObject) 
"{0c334284-9a41-4de1-99b3-a7e87e8ff07e}" | Out-Null
$template1 | Set-IntegerElement ([BcdOSLoaderElementTypes]::Integer_NxPolicy) 0 | Out-Null
$template1 | Set-BooleanElement ([BcdOSLoaderElementTypes]::Boolean_DetectKernelAndHal) 
             1 | Out-Null
$template1 | Set-BooleanElement ([BcdOSLoaderElementTypes]::Boolean_WinPEMode) 1 | Out-Null
$template1 | Set-StringElement ([uint32]"0x42000002") "\system32\winload.efi" | Out-Null
$template1 | Set-IntegerElement ([uint32]"0x45000001") 2 | Out-Null
$template1 | Set-IntegerListElement 
([uint32]"0x47000005") @(([uint32]"0x12000004"),3) | Out-Null
Windows 安装程序
-------------
标识符 {default}
locale en-US
inherit {bootloadersettings}
systemroot \windows
nx OptOut
detecthal
winpe
custom:42000002 \system32\winload.exe
custom:42000003 \boot.wim
custom:45000001 2
custom:47000005 301989892
  1
$setup1 = $BcdStore | Create-Object -Id "{cbd971bf-b7b8-4885-951a-fa03044f5d71}" 
          -Type ([uint32]"0x10200003")
$setup1 | Set-PreferredLocale "en-US" | Out-Null
$setup1 | Set-InheritedObjects @($bootloadersettings) | Out-Null
$setup1 | Set-StringElement ([BcdOSLoaderElementTypes]::String_SystemRoot) 
          "\windows" | Out-Null
$setup1 | Set-IntegerElement ([BcdOSLoaderElementTypes]::Integer_NxPolicy) 1 | Out-Null
$setup1 | Set-BooleanElement 
          ([BcdOSLoaderElementTypes]::Boolean_DetectKernelAndHal) 1 | Out-Null
$setup1 | Set-BooleanElement ([BcdOSLoaderElementTypes]::Boolean_WinPEMode) 1 | Out-Null
$setup1 | Set-StringElement ([uint32]"0x42000002") "\system32\winload.exe" | Out-Null
$setup1 | Set-StringElement ([uint32]"0x42000003") "\boot.wim" | Out-Null
$setup1 | Set-IntegerElement ([uint32]"0x45000001") 2 | Out-Null
$setup1 | Set-IntegerListElement 
([uint32]"0x47000005") @(([uint32]"0x12000004"),1) | Out-Null
Windows 安装程序
-------------
标识符 {7254a080-1510-4e85-ac0f-e7fb3d444736}
locale en-US
inherit {bootloadersettings}
systemroot \windows
nx OptOut
detecthal
winpe
custom:42000002 \system32\winload.efi
custom:42000003 \boot.wim
custom:45000001 2
custom:47000005 301989892
  1
$setup2 = $BcdStore | Create-Object 
-Id "{7254a080-1510-4e85-ac0f-e7fb3d444736}" -Type ([uint32]"0x10200003")
$setup2 | Set-PreferredLocale "en-US" | Out-Null
$setup2 | Set-InheritedObjects @($bootloadersettings) | Out-Null
$setup2 | Set-StringElement 
          ([BcdOSLoaderElementTypes]::String_SystemRoot) "\windows" | Out-Null
$setup2 | Set-IntegerElement ([BcdOSLoaderElementTypes]::Integer_NxPolicy) 1 | Out-Null
$setup2 | Set-BooleanElement 
          ([BcdOSLoaderElementTypes]::Boolean_DetectKernelAndHal) 1 | Out-Null
$setup2 | Set-BooleanElement ([BcdOSLoaderElementTypes]::Boolean_WinPEMode) 1 | Out-Null
$setup2 | Set-StringElement ([uint32]"0x42000002") "\system32\winload.efi" | Out-Null
$setup2 | Set-StringElement ([uint32]"0x42000003") "\boot.wim" | Out-Null
$setup2 | Set-IntegerElement ([uint32]"0x45000001") 2 | Out-Null
$setup2 | Set-IntegerListElement 
([uint32]"0x47000005") @(([uint32]"0x12000004"),1) | Out-Null
Windows 引导管理器
--------------------
标识符 {bootmgr}
路径 \EFI\Microsoft\Boot\bootmgfw.efi
description Windows 引导管理器
locale en-US
inherit {globalsettings}
默认 {default}
timeout 30
custom:45000001 1
$bootManager = $BcdStore | Create-Object -Id $bootmgr -Type ([uint32]"0x10100002")
$bootManager | Set-ApplicationPath "\EFI\Microsoft\Boot\bootmgfw.efi" | Out-Null
$bootManager | Set-Description "Windows Boot Manager" | Out-Null
$bootManager | Set-PreferredLocale "en-US" | Out-Null
$bootManager | Set-InheritedObjects @($globalsettings) | Out-Null
$bootManager | Set-ObjectElement ([BcdBootMgrElementTypes]::Object_DefaultObject) 
"{cbd971bf-b7b8-4885-951a-fa03044f5d71}" | Out-Null
$bootManager | Set-IntegerElement ([BcdBootMgrElementTypes]::Integer_Timeout) 30 | Out-Null
$bootManager | Set-IntegerElement ([uint32]"0x45000001") 1 | Out-Null

PowerShell BCD 代码

以下代码可以保存到文件中并使用以下命令链接

. ("FileName.ps1")

此代码不完整。尽管 WMI 方法已定义,但仍可为对象类型添加新的枚举器,并且许多从 Microsoft 复制的枚举器仍可能不正确。此代码只是一个基础。

try {
    $check = ($deviceMethods -eq [Kernel32.NativeMethods])
}
catch {
$deviceMethods = Add-Type -MemberDefinition @'
[DllImport("Kernel32.dll", 
EntryPoint = "QueryDosDeviceA", CharSet = CharSet.Ansi, SetLastError=true)]
public static extern int QueryDosDevice
(string lpDeviceName, System.Text.StringBuilder lpTargetPath, int ucchMax);
'@ -Name NativeMethods -Namespace Kernel32 -PassThru
}

function Get-DosDevice {
Param([Parameter(Mandatory=$true, Position=0)]$DriveLetter)
    $sb = New-Object System.Text.StringBuilder(30)
    $ret = $deviceMethods::QueryDosDevice($DriveLetter, $sb, 30)

    if($ret -gt 0) {
        $sb.ToString()
    }
}

function Has-Role {
    param([Security.Principal.WindowsBuiltInRole]$Role = 
          [Security.Principal.WindowsBuiltInRole]::Administrator)
    
    $identity = [Security.Principal.WindowsIdentity]::GetCurrent()
    $principal = New-Object Security.Principal.WindowsPrincipal $identity
    return $principal.IsInRole($Role)
}


function Get-StaticBcdStore {
    $SWbemLocator = New-Object -ComObject WbemScripting.SWbemLocator
    $wmi = $SWbemLocator.ConnectServer(".","root\wmi")
    $wmi.Get("BcdStore")
}

function Set-InheritedObjects {
Param([Parameter(Position=0)]$Value, [Parameter(ValueFromPipeLine=$true)]$BcdObject)
    $BcdObject | Set-ObjectListElement 
    -Type ([BcdLibraryElementTypes]::ObjectList_InheritedObjects) $Value
}

function Set-ApplicationPath {
Param([Parameter(Position=0)][string]$Value, [Parameter(ValueFromPipeLine=$true)]$BcdObject)
    $BcdObject | Set-StringElement ([BcdLibraryElementTypes]::String_ApplicationPath) $Value
}

function Set-Description {
Param([Parameter(Position=0)][string]$Value, [Parameter(ValueFromPipeLine=$true)]$BcdObject)
    $BcdObject | Set-StringElement ([BcdLibraryElementTypes]::String_Description) $Value
}

function Set-PreferredLocale {
Param([Parameter(Position=0)][string]$Value, [Parameter(ValueFromPipeLine=$true)]$BcdObject)
    $BcdObject | Set-StringElement ([BcdLibraryElementTypes]::String_PreferredLocale) $Value
}

##########################
###     COM Helper     ###
##########################

function New-InParameter {
Param([Parameter(Position=0)]$Method, [Parameter(ValueFromPipeLine=$true)]$Object)
    $Object.Methods_.Item($Method).InParameters.SpawnInstance_()
}

function Get-PropertyValue {
Param([Parameter(Position=0)]$Property, [Parameter(ValueFromPipeLine=$true)]$Object)
    $Object.Properties_.Item($Property).Value
}

function Set-PropertyValue {
Param([Parameter(Position=0)]$Property, 
[Parameter(Position=1)]$Value, [Parameter(ValueFromPipeLine=$true)]$Object)
    $Object.Properties_.Item($Property).Value=$Value
}

# 20201101 Work Around Posted for exception: 
Unable to cast object of type 'System.UInt32' to type 'System.String'
function Invoke-Method {
Param([Parameter(Position=0)]$Method, 
[Parameter(Position=1)]$ParameterNames, [Parameter(Position=2)]$ParameterValues,
    [Parameter(ValueFromPipeLine=$true)]$Object)
    if($ParameterNames -eq $null -or $ParameterValues -eq $null) {
        # If the method has required parameters: "The remote procedure call failed."
        $Object.ExecMethod_($Method)
    }
    else {
        $in = $Object.Methods_.Item($Method).InParameters.SpawnInstance_()
        if($ParameterNames.GetType() -eq [System.String]) {
            $prop = $in.Properties_.Item($ParameterNames)
            $prop.GetType().InvokeMember("Value", 
            [System.Reflection.BindingFlags]::SetProperty,$null,$prop,@($ParameterValues))
        }
        else {
            for($i = 0; $i -lt $ParameterNames.LongLength; $i++) {
                if($ParameterValues[$i] -ne $null) {
                    $prop = $in.Properties_.Item($ParameterNames[$i])
                    if($ParameterValues[$i] -is [array]) {
                        $prop.GetType().InvokeMember("Value", 
                        [System.Reflection.BindingFlags]::SetProperty,
                        $null,$prop,@(,$ParameterValues[$i]))
                    } else {
                        $prop.GetType().InvokeMember("Value", 
                        [System.Reflection.BindingFlags]::SetProperty,
                        $null,$prop,@($ParameterValues[$i]))
                    }
                }
            }
        }

        $Object.ExecMethod_($Method, $in)
    }
}

function Release-ComObject {
    Param([Parameter(Position=0, ValueFromPipeLine=$true)]$ComObject)
    [System.Runtime.InteropServices.Marshal]::ReleaseComObject($ComObject)
}

###########################
###     Known GUIDs     ###
###########################

# BCD-Template (Windows 7 Pro)
$bootmgr = "{9dea862c-5cdd-4e70-acc1-f32b344d4795}"
$resumeloadersettings = "{1afa9c49-16ab-4a5c-901b-212802da9460}"
$memdiag = "{b2721d73-1db4-4c62-bf78-c548a880142d}"
$ntldr = "{466f5a88-0af2-4f76-9038-095b170dc21c}"
$dbgsettings = "{4636856e-540f-4170-a130-a84776f4c654}"
$emssettings = "{0ce4991b-e6b3-4b16-b23c-5e0d9250e5d9}"
$bootloadersettings = "{6efb52bf-1766-41db-a6b3-0ee5eff72bd7}"
$hypervisorsettings = "{7ff607e0-4395-11db-b0de-0800200c9a66}"
$globalsettings = "{7ea2e1ac-2e61-4728-aaa3-896d9d0a9f0e}"
$badmemory = "{5189b25c-5558-4bf2-bca4-289b11bd29e2}"

# BCD.doc - 2006
$fwbootmgr = "{a5a30fa2-3d06-4e9f-b5f4-a01df9d1fcba}"
$resumeapp = "{147aa509-0358-4473-b83b-d950dda00615}"

$ramdiskopt = "{AE5534E0-A924-466C-B836-758539A3EE3A}"


############################
###     Object Types     ###
############################

if(!(([System.Management.Automation.PSTypeName]"BcdBootMgrElementTypes").Type)) {
Add-Type -TypeDefinition @'
    public enum BcdBootMgrElementTypes : uint
    {
        ObjectList_DisplayOrder = 0x24000001,
        ObjectList_BootSequence = 0x24000002,
        Object_DefaultObject = 0x23000003,
        Integer_Timeout = 0x25000004,
        Boolean_AttemptResume = 0x26000005,
        Object_ResumeObject = 0x23000006,
        ObjectList_ToolsDisplayOrder = 0x24000010,
        Boolean_DisplayBootMenu = 0x26000020,
        Boolean_NoErrorDisplay = 0x26000021,
        Device_BcdDevice = 0x21000022,
        String_BcdFilePath = 0x22000023,
        Boolean_ProcessCustomActionsFirst = 0x26000028,
        IntegerList_CustomActionsList = 0x27000030,
        Boolean_PersistBootSequence = 0x26000031
    }
'@
}

if(!(([System.Management.Automation.PSTypeName]"BcdDeviceObjectElementTypes").Type)) {
Add-Type -TypeDefinition @'
    public enum BcdDeviceObjectElementTypes : uint
    {
        Integer_RamdiskImageOffset = 0x35000001,
        Integer_TftpClientPort = 0x35000002,
        Device_SdiDevice = 0x31000003,
        String_SdiPath = 0x32000004,
        Integer_RamdiskImageLength = 0x35000005,
        Boolean_RamdiskExportAsCd = 0x36000006,
        Integer_RamdiskTftpBlockSize = 0x36000007,
        Integer_RamdiskTftpWindowSize = 0x36000008,
        Boolean_RamdiskMulticastEnabled = 0x36000009,
        Boolean_RamdiskMulticastTftpFallback = 0x3600000A,
        Boolean_RamdiskTftpVarWindow = 0x3600000B
    }
'@
}

if(!(([System.Management.Automation.PSTypeName]"BcdLibrary_DebuggerType").Type)) {
Add-Type -TypeDefinition @'
    public enum BcdLibrary_DebuggerType
    {
        DebuggerSerial = 0,
        Debugger1394 = 1,
        DebuggerUsb = 2,
        DebuggerNet = 3
    }
'@
}

if(!(([System.Management.Automation.PSTypeName]"BcdLibrary_SafeBoot").Type)) {
Add-Type -TypeDefinition @'
    public enum BcdLibrary_SafeBoot
    {
        SafemodeMinimal = 0,
        SafemodeNetwork = 1,
        SafemodeDsRepair = 2
    }
'@
}

if(!(([System.Management.Automation.PSTypeName]"BcdLibraryElementTypes").Type)) {
Add-Type -TypeDefinition @'
public enum BcdLibraryElementTypes : uint
    {
        Device_ApplicationDevice = 0x11000001,
        String_ApplicationPath = 0x12000002,
        String_Description = 0x12000004,
        String_PreferredLocale = 0x12000005,
        ObjectList_InheritedObjects = 0x14000006,
        Integer_TruncatePhysicalMemory = 0x15000007,
        ObjectList_RecoverySequence = 0x14000008,
        Boolean_AutoRecoveryEnabled = 0x16000009,
        IntegerList_BadMemoryList = 0x1700000a,
        Boolean_AllowBadMemoryAccess = 0x1600000b,
        Integer_FirstMegabytePolicy = 0x1500000c,
        Integer_RelocatePhysicalMemory = 0x1500000D,
        Integer_AvoidLowPhysicalMemory = 0x1500000E,
        Boolean_DebuggerEnabled = 0x16000010,
        Integer_DebuggerType = 0x15000011,
        Integer_SerialDebuggerPortAddress = 0x15000012,
        Integer_SerialDebuggerPort = 0x15000013,
        Integer_SerialDebuggerBaudRate = 0x15000014,
        Integer_1394DebuggerChannel = 0x15000015,
        String_UsbDebuggerTargetName = 0x12000016,
        Boolean_DebuggerIgnoreUsermodeExceptions = 0x16000017,
        Integer_DebuggerStartPolicy = 0x15000018,
        String_DebuggerBusParameters = 0x12000019,
        Integer_DebuggerNetHostIP = 0x1500001A,
        Integer_DebuggerNetPort = 0x1500001B,
        Boolean_DebuggerNetDhcp = 0x1600001C,
        String_DebuggerNetKey = 0x1200001D,
        Boolean_EmsEnabled = 0x16000020,
        Integer_EmsPort = 0x15000022,
        Integer_EmsBaudRate = 0x15000023,
        String_LoadOptionsString = 0x12000030,
        Boolean_DisplayAdvancedOptions = 0x16000040,
        Boolean_DisplayOptionsEdit = 0x16000041,
        Device_BsdLogDevice = 0x11000043,
        String_BsdLogPath = 0x12000044,
        Boolean_GraphicsModeDisabled = 0x16000046,
        Integer_ConfigAccessPolicy = 0x15000047,
        Boolean_DisableIntegrityChecks = 0x16000048,
        Boolean_AllowPrereleaseSignatures = 0x16000049,
        String_FontPath = 0x1200004A,
        Integer_SiPolicy = 0x1500004B,
        Integer_FveBandId = 0x1500004C,
        Boolean_ConsoleExtendedInput = 0x16000050,
        Integer_GraphicsResolution = 0x15000052,
        Boolean_RestartOnFailure = 0x16000053,
        Boolean_GraphicsForceHighestMode = 0x16000054,
        Boolean_IsolatedExecutionContext = 0x16000060,
        Boolean_BootUxDisable = 0x1600006C,
        Boolean_BootShutdownDisabled = 0x16000074,
        IntegerList_AllowedInMemorySettings = 0x17000077,
        Boolean_ForceFipsCrypto = 0x16000079
    }
'@
}

if(!(([System.Management.Automation.PSTypeName]"BcdMemDiagElementTypes").Type)) {
Add-Type -TypeDefinition @'
    public enum BcdMemDiagElementTypes : uint
    {
        Integer_PassCount = 0x25000001,
        Integer_FailureCount = 0x25000003
    }
'@
}

if(!(([System.Management.Automation.PSTypeName]"BcdOSLoader_NxPolicy").Type)) {
Add-Type -TypeDefinition @'
    public enum BcdOSLoader_NxPolicy
    {
        NxPolicyOptIn = 0,
        NxPolicyOptOut = 1,
        NxPolicyAlwaysOff = 2,
        NxPolicyAlwaysOn = 3
    }
'@
}

if(!(([System.Management.Automation.PSTypeName]"BcdOSLoader_PAEPolicy").Type)) {
Add-Type -TypeDefinition @'
    public enum BcdOSLoader_PAEPolicy
    {
        PaePolicyDefault = 0,
        PaePolicyForceEnable = 1,
        PaePolicyForceDisable = 2
    }
'@
}

if(!(([System.Management.Automation.PSTypeName]"BcdOSLoaderElementTypes").Type)) {
Add-Type -TypeDefinition @'
    public enum BcdOSLoaderElementTypes : uint
    {
        Device_OSDevice = 0x21000001,
        String_SystemRoot = 0x22000002,
        Object_AssociatedResumeObject = 0x23000003,
        Boolean_DetectKernelAndHal = 0x26000010,
        String_KernelPath = 0x22000011,
        String_HalPath = 0x22000012,
        String_DbgTransportPath = 0x22000013,
        Integer_NxPolicy = 0x25000020,
        Integer_PAEPolicy = 0x25000021,
        Boolean_WinPEMode = 0x26000022,
        Boolean_DisableCrashAutoReboot = 0x26000024,
        Boolean_UseLastGoodSettings = 0x26000025,
        Boolean_AllowPrereleaseSignatures = 0x26000027,
        Boolean_NoLowMemory = 0x26000030,
        Integer_RemoveMemory = 0x25000031,
        Integer_IncreaseUserVa = 0x25000032,
        Boolean_UseVgaDriver = 0x26000040,
        Boolean_DisableBootDisplay = 0x26000041,
        Boolean_DisableVesaBios = 0x26000042,
        Boolean_DisableVgaMode = 0x26000043,
        Integer_ClusterModeAddressing = 0x25000050,
        Boolean_UsePhysicalDestination = 0x26000051,
        Integer_RestrictApicCluster = 0x25000052,
        Boolean_UseLegacyApicMode = 0x26000054,
        Integer_X2ApicPolicy = 0x25000055,
        Boolean_UseBootProcessorOnly = 0x26000060,
        Integer_NumberOfProcessors = 0x25000061,
        Boolean_ForceMaximumProcessors = 0x26000062,
        Boolean_ProcessorConfigurationFlags = 0x25000063,
        Boolean_MaximizeGroupsCreated = 0x26000064,
        Boolean_ForceGroupAwareness = 0x26000065,
        Integer_GroupSize = 0x25000066,
        Integer_UseFirmwarePciSettings = 0x26000070,
        Integer_MsiPolicy = 0x25000071,
        Integer_SafeBoot = 0x25000080,
        Boolean_SafeBootAlternateShell = 0x26000081,
        Boolean_BootLogInitialization = 0x26000090,
        Boolean_VerboseObjectLoadMode = 0x26000091,
        Boolean_KernelDebuggerEnabled = 0x260000a0,
        Boolean_DebuggerHalBreakpoint = 0x260000a1,
        Boolean_UsePlatformClock = 0x260000A2,
        Boolean_ForceLegacyPlatform = 0x260000A3,
        Integer_TscSyncPolicy = 0x250000A6,
        Boolean_EmsEnabled = 0x260000b0,
        Integer_DriverLoadFailurePolicy = 0x250000c1,
        Integer_BootMenuPolicy = 0x250000C2,
        Boolean_AdvancedOptionsOneTime = 0x260000C3,
        Integer_BootStatusPolicy = 0x250000E0,
        Boolean_DisableElamDrivers = 0x260000E1,
        Integer_HypervisorLaunchType = 0x250000F0,
        Boolean_HypervisorDebuggerEnabled = 0x260000F2,
        Integer_HypervisorDebuggerType = 0x250000F3,
        Integer_HypervisorDebuggerPortNumber = 0x250000F4,
        Integer_HypervisorDebuggerBaudrate = 0x250000F5,
        Integer_HypervisorDebugger1394Channel = 0x250000F6,
        Integer_BootUxPolicy = 0x250000F7,
        String_HypervisorDebuggerBusParams = 0x220000F9,
        Integer_HypervisorNumProc = 0x250000FA,
        Integer_HypervisorRootProcPerNode = 0x250000FB,
        Boolean_HypervisorUseLargeVTlb = 0x260000FC,
        Integer_HypervisorDebuggerNetHostIp = 0x250000FD,
        Integer_HypervisorDebuggerNetHostPort = 0x250000FE,
        Integer_TpmBootEntropyPolicy = 0x25000100,
        String_HypervisorDebuggerNetKey = 0x22000110,
        Boolean_HypervisorDebuggerNetDhcp = 0x26000114,
        Integer_HypervisorIommuPolicy = 0x25000115,
        Integer_XSaveDisable = 0x2500012b
    }
'@
}

if(!(([System.Management.Automation.PSTypeName]"BcdResumeElementTypes").Type)) {
Add-Type -TypeDefinition @'
    public enum BcdResumeElementTypes : uint
    {
        Reserved1 = 0x21000001,
        Reserved2 = 0x22000002,
        Boolean_UseCustomSettings = 0x26000003,
        Device_AssociatedOsDevice = 0x21000005,
        Boolean_DebugOptionEnabled = 0x26000006,
        Integer_BootMenuPolicy = 0x25000008
    }
'@
}

if(!(([System.Management.Automation.PSTypeName]"ApplicationObjectTypes").Type)) {
Add-Type -TypeDefinition @'
    public enum ApplicationObjectTypes : uint
    {
        fwbootmgr = 0x10100001,
        bootmgr = 0x10100002,
        osloader = 0x10200003,
        resume = 0x10200004,
        memdiag = 0x10200005,
        ntldr = 0x10300006,
        bootsector = 0x10400008,
        startup = 0x10400009
    }
'@
}

#########################
###     BcdObject     ###
#########################


function Enumerate-ElementTypes {
    Param([Parameter(Position=0, ValueFromPipeLine=$true)]$BcdObject)
    $BcdObject | Invoke-Method "EnumerateElementTypes" | Get-PropertyValue "Types"
}

function Enumerate-Elements {
    Param([Parameter(Position=0, ValueFromPipeLine=$true)]$BcdObject)
    $BcdObject | Invoke-Method "EnumerateElements" | Get-PropertyValue "Elements"
}

function Get-Element {
        Param([Parameter(Position=0)][uint32]$Type, 
        [Parameter(ValueFromPipeLine=$true)]$BcdObject
    )
    $BcdObject | Invoke-Method "GetElement" 
    "Type" $Type | Get-PropertyValue "Element"
}

function Get-ElementWithFlags {
        Param([Parameter(Position=0)][uint32]$Type, 
        [Parameter(Position=1)][int]$Flags, 
        [Parameter(ValueFromPipeLine=$true)]$BcdObject
    )
    $BcdObject | Invoke-Method "GetElementWithFlags" 
    "Id","Flags" $Id,$Flags | Get-PropertyValue "Element"
}

function Set-DeviceElement {
    Param(
        [Parameter(Position=0)][uint32]$Type, 
        [Parameter(Position=1)][int]$DeviceType, 
        [Parameter(Position=2)][string]$AdditionalOptions, 
        [Parameter(ValueFromPipeLine=$true)]$BcdObject
    )
    $parameterNames = "Type","DeviceType","AdditionalOptions"
    $parameterValues = $Type,$DeviceType,$AdditionalOptions
    $BcdObject | Invoke-Method "SetDeviceElement" 
    $parameterNames $parameterValues | Get-PropertyValue "ReturnValue"
}

function Set-PartitionDeviceElement {
    Param(
        [Parameter(Position=0)][uint32]$Type, 
        [Parameter(Position=1)][int]$DeviceType, 
        [Parameter(Position=2)][string]$AdditionalOptions, 
        [Parameter(Position=3)][string]$Path, 
        [Parameter(ValueFromPipeLine=$true)]$BcdObject
    )
    $parameterNames = "Type","DeviceType","AdditionalOptions","Path"
    $parameterValues = $Type,$DeviceType,$AdditionalOptions,$Path
    $BcdObject | Invoke-Method "SetPartitionDeviceElement" 
    $parameterNames $parameterValues | Get-PropertyValue "ReturnValue"
}

function Set-PartitionDeviceElementWithFlags {
    Param(
    [Parameter(Position=0)][uint32]$Type, 
    [Parameter(Position=1)][int]$DeviceType, 
    [Parameter(Position=2)][string]$AdditionalOptions, 
    [Parameter(Position=3)][string]$Path, 
    [Parameter(Position=4)][int]$Flags, 
    [Parameter(ValueFromPipeLine=$true)]$BcdObject
    )
    $parameterNames = "Type",
    "DeviceType","AdditionalOptions","Path","Flags"
    $parameterValues = $Type,$DeviceType,$AdditionalOptions,$Path,$Flags
    $BcdObject | Invoke-Method "SetPartitionDeviceElementWithFlags" 
    $parameterNames $parameterValues | Get-PropertyValue "ReturnValue"
}

function Set-FileDeviceElement {
    Param(
        [Parameter(Position=0)][uint32]$Type, 
        [Parameter(Position=1)][int]$DeviceType, 
        [Parameter(Position=2)][string]$AdditionalOptions, 
        [Parameter(Position=3)][string]$Path, 
        [Parameter(Position=4)][uint32]$ParentDeviceType, 
        [Parameter(Position=5)][string]$ParentAdditionalOptions, 
        [Parameter(Position=6)][string]$ParentPath, 
        [Parameter(ValueFromPipeLine=$true)]$BcdObject
    )
    $parameterNames = "Type","DeviceType",
    "AdditionalOptions","Path","ParentDeviceType",
    "ParentAdditionalOptions","ParentPath"
    $parameterValues = $Type,$DeviceType,$AdditionalOptions,$Path,
    $ParentDeviceType,$ParentAdditionalOptions,$ParentPath
    $BcdObject | Invoke-Method "SetFileDeviceElement" 
    $parameterNames $parameterValues | Get-PropertyValue "ReturnValue"
}

function Set-QualifiedPartitionDeviceElement {
    Param(
        [Parameter(Position=0)][uint32]$Type,
        [Parameter(Position=1)][int]$PartitionStyle, 
        [Parameter(Position=2)][string]$DiskSignature, 
        [Parameter(Position=3)][string]$PartitionIdentifier, 
        [Parameter(ValueFromPipeLine=$true)]$BcdObject
    )
    $parameterNames = "Type","PartitionStyle",
    "DiskSignature","PartitionIdentifier"
    $parameterValues = $Type,$PartitionStyle,$DiskSignature,$PartitionIdentifier
    $BcdObject | Invoke-Method "SetQualifiedPartitionDeviceElement" 
    $parameterNames $parameterValues | Get-PropertyValue "ReturnValue"
}

function Set-VhdDeviceElement {
    Param(
        [Parameter(Position=0)][uint32]$Type, 
        [Parameter(Position=1)][string]$Path, 
        [Parameter(Position=2)][uint32]$ParentDeviceType, 
        [Parameter(Position=3)][string]$ParentAdditionalOptions, 
        [Parameter(Position=4)][string]$ParentPath, 
        [Parameter(Position=5)][uint32]$CustomLocate, 
        [Parameter(ValueFromPipeLine=$true)]$BcdObject
    )
    $parameterNames = "Type","Path","ParentDeviceType",
    "ParentAdditionalOptions","ParentPath","CustomLocate"
    $parameterValues = $Type,$Path,$ParentDeviceType,
                       $ParentAdditionalOptions,$ParentPath,$CustomLocate
    $BcdObject | Invoke-Method "SetVhdDeviceElement" 
    $parameterNames $parameterValues | Get-PropertyValue "ReturnValue"
}

function Set-StringElement {
    Param(
        [Parameter(Position=0)][uint32]$Type, 
        [Parameter(Position=1)][string]$String, 
        [Parameter(ValueFromPipeLine=$true)]$BcdObject
    )
    $BcdObject | Invoke-Method "SetStringElement" 
    "Type","String" $Type,$String | Get-PropertyValue "ReturnValue"
}

function Set-ObjectElement {
    Param(
        [Parameter(Position=0)][uint32]$Type, 
        [Parameter(Position=1)][string]$Id, 
        [Parameter(ValueFromPipeLine=$true)]$BcdObject
    )
    $BcdObject | Invoke-Method "SetObjectElement" 
    "Type","Id" $Type,$Id | Get-PropertyValue "ReturnValue"
}

function Set-ObjectListElement {
    Param(
        [Parameter(Position=0)][uint32]$Type, 
        [Parameter(Position=1)]$Ids, 
        [Parameter(ValueFromPipeLine=$true)]$BcdObject
    )
    $BcdObject | Invoke-Method "SetObjectListElement" 
    "Type","Ids" $Type,$Ids | Get-PropertyValue "ReturnValue"
}

function Set-IntegerElement {
    Param(
        [Parameter(Position=0)][uint32]$Type, 
        [Parameter(Position=1)]$Integer, 
        [Parameter(ValueFromPipeLine=$true)]$BcdObject
    )
    $BcdObject | Invoke-Method "SetIntegerElement" "Type",
    "Integer" $Type,$Integer | Get-PropertyValue "ReturnValue"
}
    
function Set-IntegerListElement {
    Param(
        [Parameter(Position=0)][uint32]$Type, 
        [Parameter(Position=1)]$Integers, 
        [Parameter(ValueFromPipeLine=$true)]$BcdObject
    )
    $BcdObject | Invoke-Method "SetIntegerListElement" "Type",
    "Integers" $Type,$Integers | Get-PropertyValue "ReturnValue"
}

function Set-BooleanElement {
    Param(
        [Parameter(Position=0)][uint32]$Type, 
        [Parameter(Position=1)][bool]$Boolean, 
        [Parameter(ValueFromPipeLine=$true)]$BcdObject
    )
    $BcdObject | Invoke-Method "SetBooleanElement" "Type",
    "Boolean" $Type,$Boolean | Get-PropertyValue "ReturnValue"
}

function Delete-Element {
    Param(
        [Parameter(Position=0)][uint32]$Type, 
        [Parameter(ValueFromPipeLine=$true)]$BcdObject
    )
    $BcdObject | Invoke-Method "DeleteElement" 
    "Type" $Type | Get-PropertyValue "ReturnValue"
}


########################
###     BcdStore     ###
########################


 function Get-FilePath {
 Param([Parameter(Mandatory=$true, Position=0, ValueFromPipeLine=$true)]$BcdStore)
    $BcdStore | Get-PropertyValue "FilePath"
 }

function Open-Store {
    Param(
        [Parameter(Position=0)][string]$File="", 
        [Parameter(Mandatory=$true, ValueFromPipeLine=$true)]$BcdStore
    )
    $BcdStore | Invoke-Method "OpenStore" 
    "File" $File | Get-PropertyValue "Store"
}

function Import-Store {
    Param(
        [Parameter(Position=0)][string]$File, 
        [Parameter(Mandatory=$true, ValueFromPipeLine=$true)]$BcdStore
    )
#### This will overwrite the current system store--use with caution! ####
    $BcdStore | Invoke-Method "ImportStore" 
    "File" $File | Get-PropertyValue "ReturnValue"
}

function Import-StoreWithFlags {
    Param(
        [Parameter(Position=0)][string]$File, 
        [Parameter(Position=1)][int]$Flags=0, 
        [Parameter(Mandatory=$true, ValueFromPipeLine=$true)]$BcdStore
    )
    $BcdStore | Invoke-Method "ImportStoreWithFlags" 
    "File","Flags" $File,$Flags | Get-PropertyValue "ReturnValue"
}

function Export-Store {
    Param(
        [Parameter(Position=0)][string]$File, 
        [Parameter(Mandatory=$true, ValueFromPipeLine=$true)]$BcdStore
    )
    $BcdStore | Invoke-Method "ExportStore" 
    "File" $File | Get-PropertyValue "ReturnValue"
}

function Create-Store {
    Param(
        [Parameter(Position=0)][string]$File, 
        [Parameter(Mandatory=$true, ValueFromPipeLine=$true)]$BcdStore
    )
    $BcdStore | Invoke-Method "CreateStore" 
    "File" $File | Get-PropertyValue "Store"
}

function Delete-SystemStore {
    Param([Parameter(Mandatory=$true, Position=0, ValueFromPipeLine=$true)]$BcdStore)
    $BcdStore | Invoke-Method "DeleteSystemStore" | Get-PropertyValue "ReturnValue"
}

function Get-SystemDisk {
Param([Parameter(Mandatory=$true, Position=0, ValueFromPipeLine=$true)]$BcdStore)
    $BcdStore | Invoke-Method "GetSystemDisk" | Get-PropertyValue "Disk"
}

function Get-SystemPartition {
Param([Parameter(Mandatory=$true, Position=0, ValueFromPipeLine=$true)]$BcdStore)
    $BcdStore | Invoke-Method 
    "GetSystemPartition" | Get-PropertyValue "Partition"
}

function Set-SystemStoreDevice {
    Param(
        [Parameter(Position=0)]$Partition, 
        [Parameter(Mandatory=$true, Position=2, ValueFromPipeLine=$true)]$BcdStore
    )
    $BcdStore | Invoke-Method 
    "SetSystemStoreDevice" | Get-PropertyValue "ReturnValue"
}

function Enumerate-Objects {
    Param(
        [Parameter(Position=0)][uint32]$Type, 
        [Parameter(Mandatory=$true, ValueFromPipeLine=$true)]$BcdStore
    )
    $BcdStore | Invoke-Method "EnumerateObjects" 
    "Type" $Type | Get-PropertyValue "Objects"
}

function Open-Object {
    Param(
        [Parameter(Position=0)][string]$Id, 
        [Parameter(Mandatory=$true, ValueFromPipeLine=$true)]$BcdStore
    )
    $BcdStore | Invoke-Method "OpenObject" 
    "Id" $Id | Get-PropertyValue "Object"
}

function Create-Object {
    Param(
        [Parameter(Position=0)][uint32]$Type, 
        [Parameter(Position=1)][string]$Id, 
        [Parameter(Mandatory=$true, ValueFromPipeLine=$true)]$BcdStore
    )
    $BcdStore | Invoke-Method "CreateObject" 
    "Id","Type" $Id,$Type | Get-PropertyValue "Object"
}

function Delete-Object {
    Param(
        [Parameter(Position=0)][string]$Id, 
        [Parameter(Mandatory=$true, ValueFromPipeLine=$true)]$BcdStore
    )
    $BcdStore | Invoke-Method "DeleteObject" 
    "Id" $Id | Get-PropertyValue "ReturnValue"
}

function Copy-Object {
    Param(
        [Parameter(Position=0)][string]$SourceStoreFile, 
        [Parameter(Position=1)][string]$SourceId, 
        [Parameter(Position=2)][int]$Flags, 
        [Parameter(Mandatory=$true, ValueFromPipeLine=$true)]$BcdStore
    )
    $BcdStore | Invoke-Method "CopyObject" "SourceStoreFile",
    "SourceId","Flags" 
    $SourceStoreFile,$SourceId,$Flags | Get-PropertyValue "Object"
}

function Copy-Objects {
    Param(
        [Parameter(Position=0)][string]$SourceStoreFile, 
        [Parameter(Position=1)][uint32]$Type, 
        [Parameter(Position=2)][int]$Flags, 
        [Parameter(Mandatory=$true, ValueFromPipeLine=$true)]$BcdStore
    )
    $BcdStore | Invoke-Method "CopyObjects" "SourceStoreFile",
    "Type","Flags" 
    $SourceStoreFile,$Type,$Flags | Get-PropertyValue "ReturnValue"
}


#################################
###     Other Bcd Objects     ###
#################################

function Get-StoreFilePath {
Param([Parameter(Mandatory=$true, Position=0, ValueFromPipeLine=$true)]$BcdObject)
    $BcdObject | Get-PropertyValue "StoreFilePath"
}

function Get-Id {
Param([Parameter(Mandatory=$true, Position=0, ValueFromPipeLine=$true)]$BcdObject)
    $BcdObject | Get-PropertyValue "Id"
}

function Get-Type {
Param([Parameter(Mandatory=$true, Position=0, ValueFromPipeLine=$true)]$BcdObject)
    $BcdObject | Get-PropertyValue "Type"
}

function Get-Path {
Param([Parameter(Mandatory=$true, Position=0, ValueFromPipeLine=$true)]$BcdObject)
    $BcdObject | Get-PropertyValue "Path"
}

function Get-ElementProperty {
Param([Parameter(Mandatory=$true, Position=0, ValueFromPipeLine=$true)]$BcdObject)
    $BcdObject | Get-PropertyValue "Element"
}

function Get-Parent {
Param([Parameter(Mandatory=$true, Position=0, ValueFromPipeLine=$true)]$BcdObject)
    $BcdObject | Get-PropertyValue "Parent"
}

function Get-ObjectId {
Param([Parameter(Mandatory=$true, Position=0, ValueFromPipeLine=$true)]$BcdElement)
    $BcdElement | Get-PropertyValue "ObjectId"
}

function Get-Data {
Param([Parameter(Mandatory=$true, Position=0, ValueFromPipeLine=$true)]$BcdDeviceUnknownData)
    $BcdDeviceUnknownData | Get-PropertyValue "Data"
}

function Get-Device {
Param([Parameter(Mandatory=$true, Position=0, ValueFromPipeLine=$true)]$BcdDeviceElement)
    $BcdDeviceElement | Get-PropertyValue "Device"
}

function Get-DeviceType {
Param([Parameter(Mandatory=$true, Position=0, ValueFromPipeLine=$true)]$BcdDeviceData)
    $BcdDeviceData | Get-PropertyValue "DeviceType"
}

function Get-AdditionalOptions {
Param([Parameter(Mandatory=$true, Position=0, ValueFromPipeLine=$true)]$BcdDeviceData)
    $BcdDeviceData | Get-PropertyValue "AdditionalOptions"
}

function Get-PartitionStyle {
Param([Parameter(Mandatory=$true, Position=0, 
ValueFromPipeLine=$true)]$BcdDeviceQualifiedPartitionData)
    $BcdDeviceQualifiedPartitionData | Get-PropertyValue "PartitionStyle"
}

function Get-DiskSignature {
Param([Parameter(Mandatory=$true, Position=0, 
ValueFromPipeLine=$true)]$BcdDeviceQualifiedPartitionData)
    $BcdDeviceQualifiedPartitionData | Get-PropertyValue "DiskSignature"
}

function Get-PartitionIdentifier {
Param([Parameter(Mandatory=$true, Position=0, 
ValueFromPipeLine=$true)]$BcdDeviceQualifiedPartitionData)
    $BcdDeviceQualifiedPartitionData | Get-PropertyValue "PartitionIdentifier"
}

function Get-String {
Param([Parameter(Mandatory=$true, Position=0, 
ValueFromPipeLine=$true)]$BcdStringElement)
    Get-PropertyValue "String" -Object $BcdStringElement
}

function Get-Ids {
Param([Parameter(Mandatory=$true, Position=0, 
ValueFromPipeLine=$true)]$BcdObjectListElement)
    Get-PropertyValue "Ids" -Object $BcdObjectListElement
}

function Get-Integer {
Param([Parameter(Mandatory=$true, Position=0, 
ValueFromPipeLine=$true)]$BcdIntegerElement)
    Get-PropertyValue "Integer" -Object $BcdIntegerElement
}

function Get-Integers {
Param([Parameter(Mandatory=$true, Position=0, 
ValueFromPipeLine=$true)]$BcdIntegerListElement)
    Get-PropertyValue "Integers" -Object $BcdIntegerListElement
}

function Get-Boolean {
Param([Parameter(Mandatory=$true, Position=0, 
ValueFromPipeLine=$true)]$BcdBooleanElement)
    Get-PropertyValue "Boolean" -Object $BcdBooleanElement
}

function Get-ActualType {
Param([Parameter(Mandatory=$true, Position=0, 
ValueFromPipeLine=$true)]$BcdUnknownElement)
    Get-PropertyValue "ActualType" -Object $BcdUnknownElement
}

关注点

看起来 BCD 提供程序乐于接受为引导加载程序等对象提供的 GUID,尽管如果允许,它也会生成这些 GUID。看起来 "{" + [guid]::NewGuid() + "}" 可以作为替代。尽管在测试中没有发现不良影响:强烈建议使用 BCD 提供的 GUID。

Microsoft 文档可在此链接找到。

BCD 示例可在 Windows SDK 7.1:BootConfigurationData 示例,Windows Vista AIK:SetAutoFailover.cmd,以及Hey Scripting Guy! 中找到。

如前所述,BCD 的细节很少。我发现学习 BCD 的最佳方法是检查 BCD 文件。使用 COM 的一大好处是可以迭代 Properties_,而无需预先知道 IdType

额外说明:此代码最初是为 PowerShell 4.0 编写的,为 PowerShell 5 所需的代码更改。

历史

  • 2014年11月1日 - 首次发布
  • 2018年2月19日 - 添加了注释
  • 2020年11月1日 - 添加了 PowerShell 5 更新
© . All rights reserved.