Modifying the Nano Server Pagefile

This weekend, I’ve been working on a little pet project using an ultra-small form factor PC that I’ve got setup running Nano Server and Boot from VHD.

The setup is great and ideal for my use case however there is a problem when using Boot from VHD and that is that the operating system you are booting cannot host a pagefile inside the VHD file. When you boot a PC using a native boot VHD file, the pagefile will be automatically created on the physical partition with the most available free space and set to System Managed which means that the pagefile will swell and shrink according to demand and not perhaps on the disk or partition you want it to be on.

I started the journey trying to modify the pagefile configuration however I quickly discovered that even the PowerShell Cmdlets recommended by many other people online to use with Server Core don’t work because they rely on using WMI to modify the parameters and if you try these, you’ll very quickly find that Nano Server only accepts and extremely small subset of WMI PowerShell Cmdlets, presumably down to the compressed WMI database in Nano.

Luckily, I found one set of Cmdlets that do work on Nano Server and allows you to configure your pagefile as you desire.

Set-CimInstance -Property @{AutomaticManagedPageFile = $False}

$PageFile = Get-CimInstance -ClassName Win32_PageFileSetting
$PageFile | Remove-CimInstance

New-CimInstance -ClassName Win32_PageFileSetting -Property  @{Name= "$("P"):\pagefile.sys"}
Get-CimInstance -ClassName Win32_PageFileSetting | Set-CimInstance -Property @{InitialSize = 4096; MaximumSize = 4096}

As you’ll see, I’m using P as my pagefile drive volume and I’m setting the initial and maximum sizes to 4096MB. Simply change these to suit your needs and job’s a good one.

Setting PowerShell as the Default Shell in Server Core

As part of a little weekend project I’ve embarked on this week, I’ve built myself a pair of new Domain Controllers for my home AD environment running on Server Core. Not only does using Server Core for Domain Controllers make great sense because they take up less resources (CPU, Memory and Storage) but they also need less patching which means we can keep them up more often. Sure, it would be nice to be able to use Nano Server for Domain Controllers but least in Technical Preview 5 at the time of writing, this isn’t a role that’s available. DNS is but AD isn’t and hopefully it will come.

Living in the present though, with Windows Server 2012 R2 and Server Core being the best we can do for Active Directory, there is a problem that most people will notice when they start using Server Core and that is that it uses Command Prompt as it’s default shell. This means that if you want to use any PowerShell Cmdlets, you need to step up to PowerShell first. I know this doesn’t seem like a hardship but if you do it enough, it gets tiresome, especially when you think that the Active Directory Cmdlets all live in PowerShell.

Luckily, we can fix this and make PowerShell the default shell in Server Core. If you’ve only got one server to do this against then the easiest thing to do it do it manually but if you’ve got a larger estate of Server Core machines, you can go it with Group Policy Preferences too.

Setting PowerShell as the Default Shell Manually

If you’ve only got one server, a couple of servers or maybe your Server Core machines are workgroup members so you can’t use Group Policy and if any of these are true, the manual method is for you. It’s a simple PowerShell one-liner:

Set-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon' -Name Shell -Value 'PowerShell.exe -NoExit'

 Setting PowerShell as the Default Shell via Group Policy

As I mentioned, we can use a Group Policy Object to ensure that all of our Server Core machines get PowerShell as their default shell.

The first step is to setup a WMI Filter in Active Directory to detect Server Core machines and the second is to create and link the GPO itself. To create a new WMI Filter, using Group Policy Management Console create a new WMI Filter. Name it whatever you chose but I called mine Windows Server 2012 R2 Server Core Only. For the query itself, use the following WMI Query:

SELECT InstallState FROM Win32_OptionalFeature WHERE (Name = "Server-Gui-Shell") AND (InstallState = "2")

To break it down, this queries WMI in the Win32_OptionalFeature class and grabs the InstallState property. It then checks to see whether InstallState is equal two for the Server-Gui-Shell value. In Windows server 2008 and 2008 R2, this was a little easier as Server GUI and Server Core identified themselves as different SKUs of the operating system however because Windows Server 2012 R2 allows us to install and uninstall the GUI as a feature that means there isn’t a different in the SKU so the way to tell the two apart is the installation state of the Server-Gui-Shell feature. On a server with a GUI, this will equal 1 and on a server without the GUI this will equal 2.

With the WMI Filter now created, we can create the GPO itself. Create a new GPO and configure it to use the WMI Filter we just created. Once created and filtered, open up the GPO Editor so that we can add our setting.

With the GPO Editor, expand Computer Configuration Preferences Windows Preferences Registry. Right-click the Registry node on the left and select New Registry Item and configure the registry item as follows:

Action: Update
Hive: HKEY_LOCAL_MACHINE
Key Path: SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon
Value Name: Shell
Value Type: REG_SZ
Value Data: PowerShell.exe -NoExit

Once you set this, hit OK and you’re done. Link the GPO to an OU in your Active Directory hierarchy that contains your servers and once it has applied, you’ll start to get PowerShell as your default prompt when you logon. Because the WMI Filter only applies to Server Core machines, it’s safe to link this GPO to a root OU that contains all of your servers so that when any Server Core machines get dropped in, they will automatically pick this GPO up.