Save Bcdedit Firmware to Array in Batch File

64 views Asked by At

Help me to create a batch script, and get the same result as this powershell script:

function FWList {
    $FWStore = bcdedit /enum firmware
    $FWOS = ($FWStore | select-string identifier,device,path,description) -notmatch '{fwbootmgr}'
    for ( $n=0; $n -lt $FWOS.count; $n++ ) {
        if ( $FWOS[$n] -match 'identifier' ) {
            if ( $FWOS[$($n + 1 )] -match 'device' ) {
                [PsCustomObject]@{
                    des  = $FWOS[$($n + 3)].line.TrimStart('description').Trim()
                    id   = $FWOS[$n].line.Split()[-1]
                    path = $FWOS[$($n + 2)].line.Split()[-1]
                    dev  = $FWOS[$($n + 1)].line.Split()[-1]
                }
            } else {
            [PsCustomObject]@{
                    des  = $FWOS[$($n + 1)].line.TrimStart('description').Trim()
                    id   = $FWOS[$n].line.Split()[-1]
                }
            }
        }
    }
}

# Example Usage
FWList | Format-List #To show in List view
FWList | Format-Table #To show in Table view
(FWList)[1..3] | Foreach {$_.des}
Pause

Example: "FWList | Format-List"

The output:

des  : Windows Boot Manager
id   : {bootmgr}
path : \EFI\Microsoft\Boot\bootmgfw.efi
dev  : partition=\Device\HarddiskVolume3

des : ATA HDD: ADATA SU650
id  : {ed2a2e5c-bb68-11ee-89e6-806e6f6e6963}

In this script I can easily get value of any Firmwares saved in array.

I tried like this but confused about how to continue...

@echo off
setlocal ENABLEDELAYEDEXPANSION
set "FWOSList=bcdedit /enum firmware ^| findstr "identifier description device path" ^| findstr /v "{fwbootmgr}""
set arr=0
for /F "usebackq tokens=1-4" %%a in ( `%FWOSList%` ) DO (
    if /I "%%a[%arr%]"=="identifier" set ID[%arr%]=%%b
    set /a arr+=1

)
rem get description, identifier, device, path
1

There are 1 answers

3
mklement0 On BEST ANSWER

Note:

  • In order for the bcdedit /enum firmware call at the heart of your solution to succeed, it must be run from an elevated session. Therefore, so must the code below.

From your own batch-file attempt it looks like you're only looking for the values on the lines that start with identifier, except for the line whose value is {fwbootmgr}.

@echo off & setlocal enableDelayedExpansion

:: Loop over all "identifier" lines of interest and store the 2nd
:: whitespace-separated token of each 
:: in individual ID[%ndx%] variables that emulate an array.
set i=0
for /f "usebackq tokens=2" %%a in (`
  bcdedit /enum firmware ^| findstr "^identifier " ^| findstr /v "{fwbootmgr}"
`) do set "ID[!i!]=%%a" & set /a i=i+1

:: Example processing:

:: Print all ID[%ndx%] variables that were created.
echo -- Resulting ID[%%ndx%%] variables:
set ID[

:: Target a specific variable, the 2nd one in this example.
set i=1
echo -- Value of ID[%i%]:
echo !ID[%i%]!

Note:

  • If you need to ensure that no preexisting Item[%ndx%] variables exist, place the following before the for /f call:

    for /f "delims==" %%i in ('Set Item[ 2^>NUL') do set "%%i="
    

If you want to capture all values, in multiple emulated arrays each corresponding to one of the properties in the output from your PowerShell code:

  • Emulating what the PowerShell code does in a batch file would be exceedingly cumbersome.

  • Therefore, call your PowerShell code from your batch file, via powershell.exe, the Windows PowerShell CLI.

    • While it is possible to use multiline PowerShell commands from a batch file, doing so requires careful escaping - see this answer. The solution below therefore uses a single-line representation of the code in your question.
  • To make parsing of the output easier for your batch file, instruct the PowerShell code to produce CSV output, using ConvertTo-Csv.

@echo off & setlocal enableDelayedExpansion

set i=0
for /f "usebackq tokens=1-4 delims=," %%a in (`
  powershell -NoProfile -Command "function FWList { $FWStore = bcdedit /enum firmware; $FWOS = ($FWStore | select-string identifier,device,path,description) -notmatch '{fwbootmgr}'; for ( $n=0; $n -lt $FWOS.count; $n++ ) { if ( $FWOS[$n] -match 'identifier' ) { if ( $FWOS[$($n + 1 )] -match 'device' ) { [PsCustomObject]@{ des = $FWOS[$($n + 3)].line.TrimStart('description').Trim(); id = $FWOS[$n].line.Split()[-1]; path = $FWOS[$($n + 2)].line.Split()[-1]; dev = $FWOS[$($n + 1)].line.Split()[-1]; } } else { [PsCustomObject]@{ des = $FWOS[$($n + 1)].line.TrimStart('description').Trim(); id = $FWOS[$n].line.Split()[-1] } } } } }; FWList | ConvertTo-Csv -NoTypeInformation | select -Skip 1"
`) do set "DES[!i!]=%%~a" & set "ID[!i!]=%%~b" & set "PATH[!i!]=%%~c" & set "DEV[!i!]=%%~d" & set /a i=i+1

:: Example processing:

:: Print all "array variables" that were created.
echo -- Resulting DEV[%%ndx%%] variables:
set DES[
echo -- Resulting ID[%%ndx%%] variables:
set ID[
echo -- Resulting PATH[%%ndx%%] variables:
set PATH[
echo -- Resulting DEV[%%ndx%%] variables:
set DEV[