powershellcmdparameter-passingbcdedit

Unable to edit with bcdedit filelds in powershell - cmd.exe command line fails


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?


Solution

  • To pass a value enclosed in {...} as a literal (as-is) in PowerShell, you must quote it; e.g.:

    bcdedit /set "{340E0E1A-01EC-4A33-A850-8D6A09FD4CE9}" description "OS2"
    

    { and }, unlike in cmd.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):

    bcdedit --% /set {340E0E1A-01EC-4A33-A850-8D6A09FD4CE9} description "OS2"
    

    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 of cmd.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.
    < is reserved for future use, as of PowerShell 7.0

    Aside from that, with respect to variable expansion (interpolation):

    To treat metacharacters as literals, you have two options: