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:

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)


Adding reference to PowerShell dll in Visual Studio

Just another quick tip today. I wanted to create a Runspace to run some PowerShell code from C#. When I launched Visual Studio, and tried referencing PowerShell, which lives in System.Management.Automation, all I got was red wiggly underline. Similarly, the PowerShell object was not recognized.

To teach Visual Studio about the System.Management.Automation namespace, I needed to add the relevant DLL, which in my case (as I have x64 Windows 8.1) was found here: 

"%ProgramFiles(x86)%\Reference Assemblies\Microsoft\WindowsPowerShell\3.0\System.Management.Automation.dll"

Once I add it to the References, wigglies go away and I can now use all the namespace has to offer:

Oh, if you are already in PowerShell console, you can see the current assembly location using this:

D:\> [psobject].assembly |fl
CodeBase               : file:///D:/WINDOWS/Microsoft.Net/assembly/GAC_MSIL/System.Management.Automation/v4.0_3.0.0.0__31bf3856ad364e35/System.Management.Automation.dll
EntryPoint             :
EscapedCodeBase        : file:///D:/WINDOWS/Microsoft.Net/assembly/GAC_MSIL/System.Management.Automation/v4.0_3.0.0.0__31bf3856ad364e35/System.Management.Automation.dll
FullName               : System.Management.Automation, Version=, Culture=neutral, PublicKeyToken=31bf3856ad364e35
GlobalAssemblyCache    : True
HostContext            : 0
ImageFileMachine       :
ImageRuntimeVersion    : v4.0.30319
Location               : D:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System.Management.Automation\v4.0_3.0.0.0__31bf3856ad364e35\System.Management.Automation.dll
ManifestModule         : System.Management.Automation.dll
MetadataToken          :
PortableExecutableKind :
ReflectionOnly         : False

Fixing Visual Studio Login Issue

If you are seeing messages from your Visual Studio (Express) complaining that your trial expired after 30 days, you need to sign in to your Visual Studio (and/or Microsoft Account).

OK. that was stating the obvious. Here is the frustrating part. You are trying to login but you cannot and you get the following error:

Browser is security restricted or JavaScript is disabled

I was surprised with this message because I do not recall disabling Javascript  on my Internet Explorer. Anyway, to enable Javascript may not be obvious:

  • Launch Inernet Explorer (v11 in my case)
  • Click Tools > Internet Options > Security
  • Click Internet
  • Click Custom level
  • Scroll all the way near the bottom
  • Under Scripting > Active Scripting, click "Enable"
  • click OK and close.

That should do it. Now you can sign in to your account, and activate your copy of VS Express.