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, are metacharacters, i.e., characters that 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.
Alternatively, you can
`-escape the unquoted metacharacters individually:bcdedit /set `{340E0E1A-01EC-4A33-A850-8D6A09FD4CE9`} description "OS2"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):Caveat: While
--%works as expected if all your arguments are literals, as in your case, in general it prevents you from using PowerShell variables and expressions as / in arguments, and can have other unexpected side effects - see this answer.Optional Background Information
Unless interpolation of PowerShell variables and expression is needed,
--%allows reuse ofcmd.execommand 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.<is reserved for future use, as of PowerShell 7.0Aside from that, with respect to variable expansion (interpolation):
cmd.exeonly expands%...%-enclosed variable names (e.g.,%PATH%), whereas PowerShell requires$-prefixed variable names (e.g.,$env:PATHor$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.exeat all.To treat metacharacters as literals, you have two options:
Enclose them in quoted strings:
cmd.exeand 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 for the full story.