My approach would look somewhat like this:
(bcdedit /enum | Out-String) -split '(?<=\r\n)\r\n' | ForEach-Object {
$name, $data = $_ -split '\r\n---+\r\n'
$props = [ordered]@{
'name' = $name.Trim()
}
$data | Select-String '(?m)^(\S+)\s\s+(.*)' -AllMatches |
Select-Object -Expand Matches |
ForEach-Object { $props[$_.Groups[1].Value] = $_.Groups[2].Value.Trim() }
[PSCustomObject]$props
}
The above code basically starts with merging the bcdedit
output into a single string like the other answers do, then splits that string into blocks of boot configuration data. Each of these blocks is then split again to separate the title from the actual data. The title is added to a hashtable as the name of the boot config section, then the data block is parsed with a regular expression for key/value pairs. These are appended to the hashtable, which is finally converted to a custom object.
Because of the the ordered
and PSCustomObject
type accelerators the code requires at least PowerShell v3.
Of course there are various optimizations you could apply to the basic example code above. For instance, different boot config sections might have different properties. The boot manager section has properties like toolsdisplayorder
and timeout
that are not present in the boot loader section, and the boot loader section has properties like osdevice
and systemroot
that are not present in the boot manager section. If you want a consistent set of properties for all generated objects you could pipe them through a Select-Object
with a list of the properties you want your objects to have, e.g.:
... | Select-Object 'name', 'identifier', 'default', 'osdevice' 'systemroot'
Properties not present in the list will be dropped from the objects, while properties that are not present in an object will be added with an empty value.
Also, instead of creating all values as strings you could convert them to a more fitting type or just modify the value, e.g. to remove curly brackets from a string.
... | ForEach-Object {
$key = $_.Groups[1].Value
$val = $_.Groups[2].Value.Trim()
$val = $val -replace '^\{(.*)\}$', '$1'
if ($val -match '^[a-f0-9]{8}(?:-[a-f0-9]{4}){3}-[a-f0-9]{12}$') {
$val = [guid]$val
} elseif ($val -eq 'yes' -or $val -eq 'true') {
$val = $true
} elseif ($val -eq 'no' -or $val -eq 'false') {
$val = $false
} elseif ($key -eq 'locale') {
$val = [Globalization.CultureInfo]$val
}
$props[$key] = $val
}