bcdedit、bcdstore和powershell

0s7z1bwu  于 2023-02-23  发布在  Shell
关注(0)|答案(4)|浏览(145)

因此,我可以在powershell脚本中编写bcd命令,就像在cmd提示符中一样,例如:

bcdedit /default '{current}'

然而,我需要一个脚本,这样做:

bcdedit /default '{current}'
bcdedit /set '{otherboot}' description "my description"

如果它不这样做,它就会反过来:

bcdedit /default '{otherboot}'
bcdedit /set '{current}' description "my description"

我需要做的是在Powershell中找到另一个 Boot 的标识符,我不确定如何找到。所有谷歌搜索都说要这样做:

$bcdStore=gwmi -name root\wmi -list bcdstore -enableall
$bcdStore|gm
$result=$bcdStore.OpenStore("") # can also use explicit file name.
$store=$result.Store

但是我不知道一旦我有了商店怎么用,这似乎有点太复杂了。我的意思是应该有一个更简单的方法...不是吗?

yzxexxkh

yzxexxkh1#

我不知道用WMI做这件事的方法,但是您可以将bcdeditSelect-String结合使用:

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

bcdedit /enum的输出大致如下所示:

Windows Boot Manager
--------------------
identifier              {bootmgr}
device                  partition=\Device\HarddiskVolume1
description             Windows Boot Manager
locale                  en-US
...

Windows Boot Loader
-------------------
identifier              {current}
device                  partition=C:
path                    \Windows\system32\winload.exe
description             Windows 7
locale                  en-US
...

Windows Boot Loader
-------------------
identifier              {e0610d98-e116-11e1-8aa3-e57ee342122d}
device                  partition=C:
path                    \Windows\system32\winload.exe
description             DebugEntry
locale                  en-US
...

此输出的相关部分是Windows Boot Loader部分,与Windows Boot Manager部分不同,它有一个path记录。因此,我们可以使用此记录仅选择Windows Boot Loader部分:

Select-String "path"

由于identifier记录比path记录早2行,因此我们需要2行PreContext(不需要PostContext):

Select-String "path" -Context 2,0

现在,我们从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

由于我们只对PreContext的第一行感兴趣,因此使用ForEach-Object循环选择这两行:

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

这就把两个块简化为:

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

我们通过字符串替换移除类别(identifier):

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

正则表达式'^identifier +'匹配以单词"identifier"开头的(子)字符串,后面跟一个或多个空格,然后替换为空字符串。替换后,两个块将缩减为:

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

所以现在我们只需要过滤掉包含{current}的块,剩下的是另一个引导记录的标识符:

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

此后,变量$otherboot包含非当前引导记录的标识符。

jtjikinw

jtjikinw2#

团队!
我正在写BCDEdit解析器.我想它会很有用.

$Configs   = @() #Array contains the parsed objects
$NameArray = @()

$Pattern = '^(?<name>[a-z]*)?\s*(?<value>.*)?$'
$enum    = bcdedit /enum

foreach ($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 results
foreach ( $item in $Configs){
    $item | Format-Table
}
7uhlpewt

7uhlpewt3#

我知道这不是一个完整的答案,但它可能足以让您开始。下面的代码输出BCD知道的所有操作系统的显示名称。

$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
}
mrphzbgm

mrphzbgm4#

我的解决方案
它无法处理语言等
但英语系统...
没有问题

<# 
#example 1
Get_Boot_info | ? description -eq 'Windows 10' | select description,identifier,path | format-list

#example 2
$id = @(Get_Boot_info | ? description -eq 'Windows 10')[0].identifier
bcdedit /default $id
bcdedit /toolsdisplayorder $id /addfirst
#>

class Boot_info {
    [string]$identifier
    [string]$device
    [string]$path
    [string]$description
    [string]$locale
    [string]$inherit
    [string]$recoverysequence
    [string]$displaymessageoverride
    [string]$recoveryenabled
    [string]$isolatedcontext
    [string]$allowedinmemorysettings
    [string]$nx
    [string]$bootmenupolicy
}

function Get_Boot_info {
    
    $nl =    [System.Environment]::NewLine
    $store = bcdedit /enum | Out-String  #combine into one string
    $List =  $store -split "$nl$nl"      #split the entries, only empty new lines
    $bl =    $List -match 'Windows Boot Loader'
    $arr =   [System.Collections.ArrayList]::new()

    $bl | % {
        $obj = $_ -Split $nl
        $bi = [Boot_info]::new()
        ForEach ($itm in $obj)
        {
            if ($itm -match 'Windows Boot Loader|-------------------') {
                continue
            }
            $data = [regex]::Replace($itm, "\s+", " ").Split(' ')
            switch ($data[0])
            {
                "identifier" {$bi.identifier = $data[1]}
                "device" {$bi.device = $data[1]}
                "path" {$bi.path = $data[1]}
                "description" {$bi.description = $data[1],$data[2]}
                "locale" {$bi.locale = $data[1]}
                "inherit" {$bi.inherit = $data[1]}
                "recoverysequence" {$bi.recoverysequence = $data[1]}
                "displaymessageoverride" {$bi.displaymessageoverride = $data[1]}
                "recoveryenabled" {$bi.recoveryenabled = $data[1]}
                "isolatedcontext" {$bi.isolatedcontext = $data[1]}
                "nx" {$bi.nx = $data[1]}
                "bootmenupolicy" {$bi.bootmenupolicy = $data[1]}
            }
        }
        $arr.Add($bi) | out-null
    }
    
    return $arr
}

相关问题