This article will cover using the BCD (Boot Configuration Data) WMI provider to manipulate BCD stores from Powershell. The complete code for interacting with BCD stores, objects, and elements is provided. This article was tagged as intermediate, not because of the difficulty of the code, but the subject matter.
Background
Because of the complexity of BCD, this article will not cover BCD in dept. The purpose of this article is to demonstrate tested techniques for managing BCD stores. For this article, all BCD operations are conducted locally. Additionally, the WMI provider for BCD requires elevated privileges.
Warning
Improper modification of a system BCD store can result in an unbootable operating system. Although the bcd.mof file was completely translated into Powershell functions for the code in this article, not all methods will be covered, nor have those methods not covered by this article been extensively tested. Before using a method not described in this article, consult the Microsoft documentation. Neither Microsoft, nor the author are responsible for how this code is used.
Code Update
Support for Powershell 5 added for a COM error.
Accessing the BCD Store
For this article, the WbemScripting.SWbemLocator
object will be used to access the BCD provider. In a side by side comparison, a C# application using the System.Management
namespace and a Powershell script using WbemScripting
both use the same resources: wmiprvse
, wmiutils
, wbemsvc
, wbemcomn2
, wbemprox
, bcdprov
, and bcdsrv
(among others). For Powershell, it is much easier to use WMI scripting API. By using only COM objects, a few (simple) functions are all that will be required to access the BCD WMI provider.
Getting an instance of the static
class BcdStore
:
function Get-StaticBcdStore {
$SWbemLocator = New-Object -ComObject WbemScripting.SWbemLocator
$wmi = $SWbemLocator.ConnectServer(".","root\wmi")
$wmi.Get("BcdStore")
}
Four COM Helper Functions
Access to method parameters:
function New-InParameter {
Param([Parameter(Position=0)]$Method, [Parameter(ValueFromPipeLine=$true)]$Object)
$Object.Methods_.Item($Method).InParameters.SpawnInstance_()
}
Access to properties:
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
}
Method execution and parameter returns:
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)
}
}
Implementing BCD WMI Methods
All methods exposed by the BCD provider are available in the bcd.mof (Managed Object Format) file. For this article, and Powershell code provided, these are broken down into three main categories according to object relation: functions and properties relating only to BcdStore
, functions and properties relating only to BcdObject
, and functions and properties that relate to BcdElements
along with properties which are shared. In implementing these methods, any out parameters are used as the function's return value, otherwise, the return is a boolean indicating the success or failure of an operation.
Working with the BCD Store
To access a store and retrieve items, the following methods are used:
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"
}
To open a BCD store, the BCD file name must be specified. An empty string denotes the system store. Obtaining BCD objects requires the GUID Id of the object. Enumerating BCD objects requires an object type.
$bootmanager = Get-StaticBcdStore | Open-Store -file "" |
Open-Object "{9dea862c-5cdd-4e70-acc1-f32b344d4795}"
$bootmanager.Properties_
In this example, the well-known GUID for the Windows Boot Manager is used to get the boot manager from the system store and the COM properties are out put. The result is just the BcdObject
properties: Id
which is the well-known GUID
, StoreFilePath
which is blank because it's in the system store, and Type
which is 0x10100002.
In the previous example, the boot manager was retrieved explicitly by using the well-known GUID. However; it is also possible to retrieve this element using its type.
$bootmanagers = Get-StaticBcdStore | Open-Store "" |
Enumerate-Objects ([uint32]"0x10100002")
$bootmanagers[0].Properties_
or:
$bootmanagers = Get-StaticBcdStore | Open-Store "" | Enumerate-Objects ([uint32]"0x10000002")
$bootmanagers[0].Properties_
These examples point out the ability to enumerate objects by their type definitions. In the second example, the object type was generalized to indicate any application type object with an application code of Windows boot manager.
To create a BCD store and BCD objects, the following two methods are used:
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"
}
Like the OpenStore
method, the CreateStore
method of the BcdStore
requires a file name. Creating objects in the BCD store requires a type and an optional GUID or well-known GUID.
Get-StaticBcdStore | Create-Store "$env:TEMP\BCD-Demo" `
| Create-Object ([uint32]"0x10100001")
"{a5a30fa2-3d06-4e9f-b5f4-a01df9d1fcba}"
In this example, the well-known GUID for Firmware Boot Manager and the object type for firmware boot manager are used to create: Firmware Boot Manager. The Id
parameter is optional. To create new objects, pass only the object type, the objects Id will be populated with a GUID created by the provider. However, many objects, like this Firmware Boot Manager, can only be created with the well-known GUID and type combination.
Working with BCD Objects
Setting elements requires methods provided by the BcdObject
. What these methods have in common is the use of Type
to define the object's element to be manipulated. Microsoft's MSDN has a fairly complete (although not always accurate) list of enumerations. By this, I mean that a few enumeration values may be defined as a specific type though they are not of that type, and other enumeration values that are missing--though they can be substituted with existing values.
The following methods are used to retrieve element data from BcdObject
s:
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"
}
To get a list of elements, element types, and values, all that needs to be done is this:
$bootmanager = Get-StaticBcdStore | Open-Store -file "" |
Open-Object "{9dea862c-5cdd-4e70-acc1-f32b344d4795}"
$bootmanager | Enumerate-ElementTypes | % {
(Get-Element -Type $_ -BcdObject $bootmanager).Properties_
}
As for setting element data, the following methods will be demonstrated later, but with names like SetBooleanElement
and SetStringElement
, they are self explanatory.
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"
}
A few methods will take an array of values, these should be passed using @()
.
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"
}
Setting device data is much more complex and will also be demonstrated later:
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"
}
More methods are provided by the BcdObject
and included in the code later in this article, though not covered in this article.
Working with BCD Elements
This last section covering BCD methods will deal with the actual elements of BCD objects. In the previous sections, we covered using the BcdStore
object to open and create objects and briefly touched on using the BcdObject
to set element data. To get specific information from an element, we have to access the element's properties. A string
element has a property String
, a boolean element has a property Boolean
, and so on.
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
}
For object lists:
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
}
For device objects:
function Get-Device {
Param([Parameter(Mandatory=$true, Position=0, ValueFromPipeLine=$true)]$BcdDeviceElement)
$BcdDeviceElement | Get-PropertyValue "Device"
}
This will be the last demonstration for getting data from a BCD store. (Saving the best for last: getting device data.)
$mem = Get-StaticBcdStore | Open-Store "" |
Open-Object "{b2721d73-1db4-4c62-bf78-c548a880142d}"
$dev = $mem | Get-Element
-Type ([BcdLibraryElementTypes]::Device_ApplicationDevice) | Get-Device
$dev.Properties_
This example gets the Windows Memory Tester and retrieves the device data. This method is handy for evaluating properties for setting various device elements from code.
Finally, the Good Stuff
Now then... the ultimate goal of this article is to provide working examples for modifying a BCD store from Powershell.
Building a BCD store from scratch
For the first demonstration, the output from bcdedit
for a live system store is used to generate a new BCD store in code. The resulting BCD store is created on a drive that has been cleaned, reformatted, and reimaged in a deployment scenario. Much of bcdedit
's output has been reordered for object dependency. Enumerators and well-known GUID variables are provided in the code at the end of this article.
. ("$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
*The BCD WMI provider does not seem to implement QueryDosDevice
--unlike bcdedit
, volume letters are not accepted when setting Device
properties. Also, while building the BCD store from scratch results in a fully functional store, OS boots, hibernates, and resumes properly, booting to WinRE always results in a rebuild of the BCD store. To get the store just right, a "dummy" store has to be imported. This results in a properly functioning BCD store. (This solution was found at this link.)
EMS Settings |
------------ |
identifier | {0ce4991b-e6b3-4b16-b23c-5e0d9250e5d9} |
bootems | Yes |
$BcdStore | Create-Object -Id $emssettings -Type ([uint32]"0x20100000") | `
Set-BooleanElement ([BcdLibraryElementTypes]::Boolean_EmsEnabled) 1 | Out-Null
Debugger Settings |
----------------- |
identifier | {4636856e-540f-4170-a130-a84776f4c654} |
debugtype | Serial |
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 Defects |
----------- |
identifier | {5189b25c-5558-4bf2-bca4-289b11bd29e2} |
$BcdStore | Create-Object -Id $badmemory -Type ([uint32]"0x20100000") | Out-Null
Global Settings |
--------------- |
identifier | {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
Resume Loader Settings |
---------------------- |
identifier | {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 Settings |
------------------- |
identifier | {7ff607e0-4395-11db-b0de-0800200c9a66} |
hypervisordebugtype | Serial |
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
Boot Loader Settings |
-------------------- |
identifier | {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 Memory Tester |
--------------------- |
identifier | {b2721d73-1db4-4c62-bf78-c548a880142d} |
device | partition=S: |
path | \boot\memtest.exe |
description | Windows Memory Diagnostic |
locale | en-US |
inherit | {7ea2e1ac-2e61-4728-aaa3-896d9d0a9f0e} |
badmemoryaccess | Yes |
$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
Resume from Hibernate |
--------------------- |
identifier | {ebe94447-1944-11e4-95c4-dd9a4e7158f6} |
device | partition=C: |
path | \windows\system32\winresume.exe |
description | Windows Resume Application |
locale | en-US |
inherit | {1afa9c49-16ab-4a5c-901b-212802da9460} |
filedevice | partition=C: |
filepath | \hiberfil.sys |
debugoptionenabled | No |
$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
Device options |
-------------- |
identifier | {ebe9444a-1944-11e4-95c4-dd9a4e7158f6} |
description | Ramdisk Options |
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 Boot Loader |
------------------- |
identifier | {ebe94449-1944-11e4-95c4-dd9a4e7158f6} |
device | ramdisk=[S:]\Recovery\WindowsRE\Winre.wim,{ebe9444a-1944-11e4-95c4-dd9a4e7158f6} |
path | \windows\system32\winload.exe |
description | Windows Recovery Environment |
inherit | {6efb52bf-1766-41db-a6b3-0ee5eff72bd7} |
osdevice | ramdisk=[S:]\Recovery\WindowsRE\Winre.wim,{ebe9444a-1944-11e4-95c4-dd9a4e7158f6} |
systemroot | \windows |
nx | OptIn |
winpe | Yes |
custom:46000010 | Yes |
$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 Boot Loader |
------------------- |
identifier | {ebe94448-1944-11e4-95c4-dd9a4e7158f6} |
device | partition=C: |
path | \windows\system32\winload.exe |
description | Windows 7 |
locale | en-US |
inherit | {6efb52bf-1766-41db-a6b3-0ee5eff72bd7} |
recoverysequence | {ebe94449-1944-11e4-95c4-dd9a4e7158f6} |
recoveryenabled | Yes |
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 Boot Manager |
-------------------- |
identifier | {9dea862c-5cdd-4e70-acc1-f32b344d4795} |
device | partition=S: |
description | Windows Boot Manager |
locale | en-US |
inherit | {7ea2e1ac-2e61-4728-aaa3-896d9d0a9f0e} |
default | {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
Updating a USB BCD store
For the second demonstration, a WinPE file is added to an existing WinPE USB. Other than adding the Windows Boot Loader, it is necessary to update the ems (Emergency Management Services) setting to display the boot menu, if not already enabled. As the BCD store has an existing Ramdisk Option, a new one is not required; however, it is necessary to get the Id of the existing Device Option. Lastly, after the new boot loader is added, the Windows Boot Manager needs the display order updated to include the new boot loader.
$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
*The Boolean_EmsEnabled
that appears for the boot loader and the boot manager are not the same.
Just for fun--Building the BCD-Template
The last demonstration will recreate the BCD-Template located in system32\config. This will show some of the BCD objects not normally defined in a standard BCD store.
A few of the repetative operations have been simplified--such as the use of a Set-InheritedObjects
function to wrap Set-ObjectListElement
([BcdLibraryElementTypes]::ObjectList_InheritedObjects)
. Also, a mix of basic and verbose bcdedit
output is used to provide a more accurate result of the demonstrative code.
EMS Settings |
------------ |
identifier | {emssettings} |
bootems | Yes |
$BcdStore | Create-Object -Id $emssettings -Type ([uint32]"0x20100000") | `
Set-BooleanElement ([BcdLibraryElementTypes]::Boolean_EmsEnabled) 1 | Out-Null
Debugger Settings |
----------------- |
identifier | {dbgsettings} |
debugtype | Serial |
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 Defects |
----------- |
identifier | {badmemory} |
$BcdStore | Create-Object -Id $badmemory -Type ([uint32]"0x20100000") | Out-Null
Global Settings |
--------------- |
identifier | {globalsettings} |
inherit | {dbgsettings} |
| {emssettings} |
| {badmemory} |
$global = $BcdStore | Create-Object -Id $globalsettings -Type ([uint32]"0x20100000") | `
Set-InheritedObjects @($dbgsettings,$emssettings,$badmemory) | Out-Null
Resume Loader Settings |
---------------------- |
identifier | {resumeloadersettings} |
inherit | {globalsettings} |
$BcdStore | Create-Object -Id $resumeloadersettings -Type ([uint32]"0x20200004") | `
Set-InheritedObjects -Value @($globalsettings) | Out-Null
Windows Legacy OS Loader |
------------------------ |
identifier | {ntldr} |
path | \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 Settings |
------------------- |
identifier | {hypervisorsettings} |
hypervisordebugtype | Serial |
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
Boot Loader Settings |
-------------------- |
identifier | {bootloadersettings} |
inherit | {globalsettings} |
| {hypervisorsettings} |
$BcdStore | Create-Object -Id $bootloadersettings -Type ([uint32]"0x20200003") | `
Set-InheritedObjects @($globalsettings,$hypervisorsettings) | Out-Null
Windows Memory Tester |
--------------------- |
identifier | {memdiag} |
path | \boot\memtest.exe |
locale | en-US |
inherit | {globalsettings} |
badmemoryaccess | Yes |
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
Resume from Hibernate |
--------------------- |
identifier | {0c334284-9a41-4de1-99b3-a7e87e8ff07e} |
description | Windows Resume Application |
locale | en-US |
inherit | {resumeloadersettings} |
filepath | \hiberfil.sys |
custom:42000002 | \system32\winresume.efi |
custom:45000001 | 2 |
custom:46000004 | Yes |
$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
Resume from Hibernate |
--------------------- |
identifier | {98b02a23-0674-4ce7-bdad-e0a15a8ff97b} |
description | Windows Resume Application |
locale | en-US |
inherit | {resumeloadersettings} |
filepath | \hiberfil.sys |
custom:42000002 | \system32\winresume.exe |
custom:45000001 | 2 |
custom:46000004 | Yes |
$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 Target Template |
------------------ |
identifier | {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 | Yes |
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 Target Template |
------------------ |
identifier | {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 | Yes |
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 Setup |
------------- |
identifier | {default} |
locale | en-US |
inherit | {bootloadersettings} |
systemroot | \windows |
nx | OptOut |
detecthal | Yes |
winpe | Yes |
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 Setup |
------------- |
identifier | {7254a080-1510-4e85-ac0f-e7fb3d444736} |
locale | en-US |
inherit | {bootloadersettings} |
systemroot | \windows |
nx | OptOut |
detecthal | Yes |
winpe | Yes |
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 Boot Manager |
-------------------- |
identifier | {bootmgr} |
path | \EFI\Microsoft\Boot\bootmgfw.efi |
description | Windows Boot Manager |
locale | en-US |
inherit | {globalsettings} |
default | {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
The following code can be saved to a file and linked using:
. ("FileName.ps1")
This code is not complete. Although the WMI methods have been defined, new enumerators can be added for Object Type and many of the enumerators copied from Microsoft may still be incorrect. This code is only a foundation.
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
}
Points of Interest
It would seem that the BCD provider is content to accept a supplied GUID for objects like Boot Loader, even though it will generate these if allowed. It would also seem that "{" + [guid]::NewGuid() + "}"
is an acceptable substitute. Though no adverse effects were seen during testing: it is highly recommended to use the GUIDs provided by BCD.
Microsoft Documentation can be found at this link.
BCD examples can be found in Windows SDK 7.1: BootConfigurationData
Sample, Windows Vista AIK: SetAutoFailover.cmd, and at Hey Scripting Guy!
As previously stated, details of BCD are sparse. I found the best method of learning BCD to be examining BCD files. A large bonus of using COM is the ability to iterate the Properties_
without foreknowledge of the Id
or Type
.
Additional note: This code was originally written for Powershell 4.0, code changes were required for Powershell 5.
History
- 1st November, 2014 - Initial release
- 19th February, 2018 - Added note
- 1st November, 2020 - Powershell 5 update added