Why can't I edit the description field using bcdedit
in PowerShell?
For example, in cmd.exe
the following command:
bcdedit /set {GUID} description "OS2"
completes successfully, changing the description field for the specified GUID, but when I do the same thing from Powershell, I get the following error:
The set command specified is not valid.
Run "bcdedit /?" for command line assistance.
The parameter is incorrect.
Can someone explain this to me?
To pass a value enclosed in
{...}
as a literal (as-is) in PowerShell, you must quote it; e.g.:{
and}
, unlike incmd.exe
, have special meaning in PowerShell when used unquoted (they enclose a script block), which in this case happens to result in{
and}
simply getting removed.Quoting prevents that.
A generic alternative, available since PSv3, is to use the so-called stop-parsing symbol,
--%
, which passes all remaining arguments as-is, without interpretation by PowerShell (with the exception of expanding%...%
-enclosed environment-variable references):Optional Background Information
Unless interpolation of PowerShell variables and expression is needed,
--%
allows reuse ofcmd.exe
command lines as-is, without having to worry about PowerShell's quoting (escaping) requirements.Generally, PowerShell's metacharacters (characters that have special meaning when unquoted) are different from
cmd.exe
's and much more numerous:In addition to
cmd.exe
's metachars.,PowerShell has:
<
,>
,@
and#
only have special meaning at the start of a token.<
and&
, as of PSv5.1, are reserved for future use.Aside from that, with respect to variable expansion (interpolation):
cmd.exe
only expands%...%
-enclosed variable names (e.g.,%PATH%
), whereas PowerShell requires$
-prefixed variable names (e.g.,$env:PATH
or$HOME
) or$(...)
-enclosed expressions (subexpression operator)"..."
(double-quoted strings).'...'
(single-quoted strings) are literal strings in PowerShell (contents is used as-is, without interpolation), whereas'
has no special meaning tocmd.exe
at all.To treat metacharacters as literals, you have two options:
Enclose them in quoted strings:
cmd.exe
and PowerShell: enclose them in"..."
(but potentially with interpolation of any variable references / subexpressions also enclosed in the string); e.g.,"|"
.'...'
; e.g.,'|'
Escape them individually:
`
-escape them (backtick); e.g.,`|
"..."
, although there it is only needed to escape$
so as to prevent variable / subexpression expansion.cmd.exe
:^
-escape them (caret); e.g.,^|
"..."
, and sadly, doesn't work for escaping%
to suppress variable expansion - see this answer of mine for the full story.