Google

2014-04-19

PowerShell Gotchas: Enabling Safemode for Windows 8.1 with Bcdedit

In the last couple of days, I started to see a couple of weird issues on my my fully patched Windows 8.1 Update 1 PC. I may blog more about that later but for now, I just want to blog about a PowerShell gotcha, that might frustrate those who are switching from good ol' cmd shell to PowerShell console.

To troubleshoot the recent BSODs, I wanted to enable Safe Mode in Windows 8. Steps are well documented here: http://support.microsoft.com/kb/2809468/en-us

To do this, we need to use BCDEdit utility, which is used to manage Windows boot settings in the newer Windows OSes.

Here I am in PowerShell Admin console...

PS C:\WINDOWS\system32> bcdedit

Windows Boot Manager
--------------------
identifier              {bootmgr}
device                  partition=\Device\HarddiskVolume1
description             Windows Boot Manager
locale                  en-US
inherit                 {globalsettings}
integrityservices       Enable
default                 {current}
resumeobject            {4efceffa-37b1-11e3-9418-e54cd3928210}
displayorder            {current}
toolsdisplayorder       {memdiag}
timeout                 30


Windows Boot Loader
-------------------
identifier              {current}
device                  partition=C:
path                    \WINDOWS\system32\winload.exe
description             Windows 8.1
locale                  en-US
inherit                 {bootloadersettings}
recoverysequence        {8bcbbebd-37b2-11e3-9418-e54cd3928210}
integrityservices       Enable
recoveryenabled         Yes
allowedinmemorysettings 0x15000075
osdevice                partition=C:
systemroot              \WINDOWS
resumeobject            {4efceffa-37b1-11e3-9418-e54cd3928210}
nx                      OptIn
bootmenupolicy          Standard

Let's tell Windows 8.1 to display safe mode options
PS C:\WINDOWS\system32> bcdedit /set {bootmgr} displaybootmenu yes

The set command specified is not valid.
Run "bcdedit /?" for command line assistance.
The parameter is incorrect.


Ugh, ok. I know the command is correct but PowerShell tells us otherwise. Most of the time, dos (I really mean cmd shell) utilities work just fine in PowerShell but when they do not we can tell PowerShell to hand it over to cmd shell
PS C:\WINDOWS\system32> cmd /c bcdedit /set {bootmgr} displaybootmenu yes
The set command specified is not valid.
Run "bcdedit /?" for command line assistance.
The parameter is incorrect.

Same error. OK, I won't keep doing this. You see the curly brackets over there in the command line surrounding bootmgr, that's our problem. PowerShell is trying to parse the arguments and {} is a scriptblock in PowerShell, so we should tell it not to interpret arguments
PS C:\WINDOWS\system32> bcdedit --% /set {bootmgr} displaybootmenu yes

The operation completed successfully.
There! --% was introduced in PowerShell v3 (I believe) and is very useful when handling quotes and such that have a special meaning in PowerShell, and hence parsing them gets hairy.

Note: There are other cases where you need to tell PowerShell to use cmd shell. For example:
d:\>where ssh
## did not return anything
d:\>cmd /c where ssh
D:\Program Files (x86)\Git\bin\ssh.exe

This works because 'where' is an alias for where-object cmdlet in PowerShell. In cmd shell, it tells you where an executable is located (as would `which` in linux/mac)

No comments: