无法使用powershell中的bcdedit filelds进行编辑 - cmd.exe命令行失败

kni*_*ack 1 powershell cmd parameter-passing bcdedit

为什么我不能bcdedit在PowerShell中编辑描述字段?

例如,在cmd.exe以下命令中:

bcdedit /set {GUID} description "OS2"
Run Code Online (Sandbox Code Playgroud)

成功完成,更改指定GUID的描述字段,但是当我从Powershell执行相同操作时,我收到以下错误:

The set command specified is not valid.
Run "bcdedit /?" for command line assistance.
The parameter is incorrect.
Run Code Online (Sandbox Code Playgroud)

谁可以给我解释一下这个?

mkl*_*nt0 5

在PowerShell中传递{...}作为文字(原样)包含的值,您必须引用 ; 例如:

bcdedit /set "{340E0E1A-01EC-4A33-A850-8D6A09FD4CE9}" description "OS2"
Run Code Online (Sandbox Code Playgroud)

{并且},与不同cmd.exe,在PowerShell中使用不带引号(它们包含一个脚本块)时具有特殊含义,在这种情况下恰好导致{}简单地删除.
引用可以防止这种情况.

自PSv3以来可用通用替代方法使用所谓的停止解析符号,--%符号按原样传递所有剩余的参数,而不由PowerShell解释(扩展的%...%-enclosed环境变量引用除外):

bcdedit --% /set {340E0E1A-01EC-4A33-A850-8D6A09FD4CE9} description "OS2"
Run Code Online (Sandbox Code Playgroud)

可选背景信息

除非需要插入PowerShell变量和表达式,否则--%允许cmd.exe按原样重用命令行,而不必担心PowerShell的引用(转义)要求.

通常,PowerShell的元字符(在不带引号时具有特殊含义的字符)cmd.exes和更多的不同:

cmd.exe的metachars,

& | < >
Run Code Online (Sandbox Code Playgroud)

PowerShell有:

( ) , { } ; @ # 
Run Code Online (Sandbox Code Playgroud)

<,>,@并且#只有具有特殊含义在开始令牌.
<并且&,从PSv5.1开始,保留供将来使用.

除此之外,关于变量扩展(插值):

  • cmd.exe只扩展%...%-enclosed变量名称(例如%PATH%),而PowerShell需要$-prefixed变量名称(例如,$env:PATH$HOME)或$(...)-enclosed表达式(子表达式运算符)

    • 在两个解释器中,变量扩展(以及PowerShell中的子表达式扩展)也在内部执行"..."(双引号字符串).
  • '...'(单引号字符串)是PowerShell 中的文字字符串(内容按原样使用,没有插值),'但根本没有特殊含义cmd.exe.

要将元字符视为文字,您有两种选择:

  • 引号字符串括起来:

    • 两者cmd.exe和PowerShell:将它们包含在内"..."(但可能插入也包含在字符串中的任何变量引用/子表达式); 例如,"|".
    • 仅限PowerShell:将它们包含在内'...'; 例如,'|'
  • 单独逃脱:

    • PowerShell:`-escape them(backtick); 例如,`|
      • 这也适用于内部"...",虽然它只需要转义$以防止变量/子表达式扩展.
    • cmd.exe:^-escape them(caret); 例如,^|
      • 这只能在外面工作"...",而且遗憾的是,它不能用于逃避%压缩变量扩展 - 请参阅我的答案.