bcdedit, bcdstore and powershell bcdedit, bcdstore and powershell powershell powershell

bcdedit, bcdstore and powershell


I don't know of a way to do it with WMI, but you could use bcdedit in combination with Select-String:

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

Explanation:

The output of bcdedit /enum looks roughly like this:

Windows Boot Manager--------------------identifier              {bootmgr}device                  partition=\Device\HarddiskVolume1description             Windows Boot Managerlocale                  en-US...Windows Boot Loader-------------------identifier              {current}device                  partition=C:path                    \Windows\system32\winload.exedescription             Windows 7locale                  en-US...Windows Boot Loader-------------------identifier              {e0610d98-e116-11e1-8aa3-e57ee342122d}device                  partition=C:path                    \Windows\system32\winload.exedescription             DebugEntrylocale                  en-US...

The relevant sections of this output are the Windows Boot Loader sections, which – unlike the Windows Boot Manager section – have a path record. Thus we can use this record to select only the Windows Boot Loader sections:

Select-String "path"

Since the identifier records are 2 lines before the path records, we need 2 lines of PreContext (and no PostContext):

Select-String "path" -Context 2,0

Now we have selected the follwing two chunks from the output of bcdedit /enum:

identifier              {current}device                  partition=C:path                    \Windows\system32\winload.exe
identifier              {e0610d98-e116-11e1-8aa3-e57ee342122d}device                  partition=C:path                    \Windows\system32\winload.exe

Since we're only interested in the first line of the PreContext we select these 2 lines using a ForEach-Object loop:

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

which reduces the two chunks to this:

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

from which we remove the category (identifier) via string replacement:

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

The regular expression '^identifier +' matches a (sub)string starting with the word "identifier" followed by one or more spaces, which is replaced with the empty string. After this replacement the two chunks are reduced to this:

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

So now we only need to filter out the chunk containing {current} and what's left is the identifier of the other boot record:

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

After this, the variable $otherboot contains the identifier of the not-current boot record.


I know this is not a complete answer, but it might be enough to get you started. The code below outputs the display names of all the operating systems that the BCD is aware of.

$cxOptions= new-object System.Management.ConnectionOptions$cxOptions.Impersonation=[System.Management.ImpersonationLevel]::Impersonate$cxOptions.EnablePrivileges=$true$mgmtScope=new-object System.Management.ManagementScope -ArgumentList "root\WMI",$cxOptions$mgmtPath=new-object System.Management.ManagementPath -ArgumentList 'root\WMI:BcdObject.Id="{9dea862c-5cdd-4e70-acc1-f32b344d4795}",StoreFilePath=""'$mgmtObject=new-object System.Management.ManagementObject -ArgumentList $mgmtScope,$mgmtPath,$null# Determine what elements exist in the object and output their value in HEX format#$mgmtObject.EnumerateElementTypes().types | % { "{0:X0}" -f $_ }$objBCD=$mgmtObject.GetElement(0x24000001)$objElements=$objBCD.GetPropertyValue("Element")$strOldID="{9dea862c-5cdd-4e70-acc1-f32b344d4795}"for ($i=0; $i -lt $objElements.Ids.Count; $i++) {  $mgmtPath.Path=$mgmtPath.Path.Replace($strOldID,$objElements.Ids[$i])  $strOldID=$objElements.Ids[$i]  $objBCDId=new-object System.Management.ManagementObject -ArgumentList $mgmtScope,$mgmtPath,$null  $strOS=$objBCDId.GetElement(0x12000004)  $strOS.Element.String}


Team!

I`am wrote the BCDEdit parser.I think it will be usefull.

$Configs   = @() #Array contains the parsed objects$NameArray = @()$Pattern = '^(?<name>[a-z]*)?\s*(?<value>.*)?$'$enum    = bcdedit /enumforeach ($item in $enum ){    if ( $item.trim() ){        $res = [regex]::matches( $item, $pattern )        if ( $res ){            $Value = $res[0].Groups['value'].value             $Name  = $res[0].Groups['name'].value            if ( $Value ){                if ( $Name ){                    $PSO = [PSCustomObject]@{                        Name  = $Name                        Value = $Value                    }                    $NameArray += $PSO                }                Else {                    if ( $NameArray.count ){                        ( $NameArray | Select-Object -last 1 ).Value += "; $Value"                    }                }            }                    }    }    Else {        if ( $NameArray ){            $Configs  += ,$NameArray            $NameArray = @()        }    }}#Show resultsforeach ( $item in $Configs){    $item | Format-Table}