Server Core: Save money.

I remember an internal joke floating around Microsoft in 2007, about a new way to deploy Windows Server.  There was an ad campaign around Windows Vista at the time that said ‘The Wow Starts Now!’  When they spoke about Server Core they joked ‘The Wow Stops Now!’

Server Core was a new way to deploy Windows Server.  It was not a different license or a different SKU, or even different media.  You simply had the option during the installation of clicking ‘Server Core’ which would install the Server OS without the GUI.  It was simply a command prompt with, at the time, a few roles that could be installed in Core.

While Server Core would certainly save some resources, it was not really practical in Windows Server 2008, or at least not for a lot of applications.  There was no .NET, no IIS, and a bunch of other really important services could not be installed on Server Core.  In short, Server Core was not entirely practical.

Fast Forward to Windows Server 2012 (and R2) and it is a completely different story.  Server Core a fully capable Server OS, and with regard to resources the savings are huge.  So when chatting with the owner of a cloud services provider recently (with hundreds of physical and thousands of virtual servers) I asked what percentage of his servers were running Server Core, and he answered ‘Zero’.  I could not believe my ears.

The cloud provider is a major Microsoft partner in his country, and is on the leading edge (if not the bleeding edge) on every Microsoft technology.  They recently acquired another datacentre that was a VMware vCloud installation, and have embarked on a major project to convert all of those hosts to Hyper-V through System Center 2012.  So why not Server Core?

The answer is simple… When Microsoft introduced Server Core in 2008 they tried it out, and recognizing its limitations decided that it would not be a viable solution for them.  It had nothing to do with the command line… the company scripts and automates everything in ways that make them one of the most efficient datacentres I have ever seen.  They simply had not had the cycles to re-test Server Core in Server 2012 R2 yet.

We sat down and did the math.  The Graphical User Environment (GUI) in Windows Server 2012 takes about 300MB of RAM – a piddling amount when you consider the power of today’s servers.  However in a cloud datacentre such as this one, in which every host contained 200-300 virtual machines running Windows Server, that 300MB of RAM added up quickly – a host with two hundred virtual machines required 60GB of RAM just for GUIs.  If we assume that the company was not going to go out and buy more RAM for its servers simply for the GUI, it meant that, on average, a host comfortably running 200 virtual machines with the GUI would easily run 230 virtual machines on Server Core.

In layman’s terms, the math in the previous paragraph means that the datacentre capacity could increase by fifteen percent by converting all of his VMs to Server Core.  If the provider has 300 hosts running 200 VMs each (60,000 VMs), then an increased workload of 15% translates to 9,000 more VMs.  With the full GUI that translates to forty-five more hosts (let’s conservatively say $10,000 each), or an investment of nearly half a million dollars.  Of course that is before you consider all of the ancillary costs – real estate, electricity, cooling, licensing, etc…  Server Core can save all of that.

Now here’s the real kicker: Had we seen this improvement in Windows Server 2008, it still would have been a very significant cost to converting servers from GUI to Server Core… a re-install was required.  With Windows Server 2012 Server Core is a feature, or rather the GUI itself is a feature that can be added or removed from the OS, and only a single reboot is required.  While the reboot may be disruptive, if managed properly the disruption will be minimal, with immense cost savings.

If you have a few servers to uninstall the GUI from then the Server Manager is the easy way to do it.  However if you have thousands or tens of thousands of VMs to remove it from, then you want to script it.  As usual PowerShell provides the easiest way to do this… the cmdlet would be:

Uninstall-WindowsFeature Server-Gui-Shell –restart

There is also a happy medium between the GUI and Server Core called MinShell… you can read about it here.  However remember that in your virtualized environment you will be doing a lot more remote management of your servers, and there is a reason I call MinShell ‘the training wheels for Server Core.’

There’s a lot of money to be saved, and the effort is not significant.  Go ahead and try it… you won’t be disappointed!

A response to a VMware article… written by someone I respect.

English: VMware vSphere in the Enterprise

While he may not be very well know to the Microsoft community, Mike Laverick is a legend in VMware circles.  Mike owns a blog called RTFM Education, a source of white papers for VMware technology, although he did start out as a Microsoft Certified Trainer.  He now works for VMware as a Senior Cloud Infrastructure Evangelist.  I was very happy to read on his blog that he has decided to try learning Hyper-V and Microsoft’s Private Cloud.  Unfortunately from what I can tell he was still trying to think way too VMware, rather that trying to learn the Microsoft way of doing things.

(To read the article follow this link:

This is a problem that I see all the time, and going both ways.  When I was teaching vSphere Infrastructure classes my Microsoft-focused students had a hard time getting out of the Microsoft mindset.  When I teach Microsoft courses, my VMware students have the same problem going the other direction.  It would be much easier if people would open their minds and just let the technology flow… but then I have been a Star Wars fan for too long so I believe in that sort of thing.

I found several points of the article quite amusing.  Mike opens the article with a picture and quote from the book Windows NT Microsoft Cluster Server.  The first words that he actually types are ‘Mmm, so much has changed since then or has it?’  I am sorry Mike, but to even insinuate that Microsoft Clustering in Windows Server 2012 R2 is anywhere near the disaster that was clustering in Windows NT (or Server 2000, or Server 2003) is a joke.  Yes, you have to have the proper pieces in place, and yes, you have to configure it properly.  You even have to spend a little time learning Microsoft Clustering and how it works.  If you were to spend thirty minutes with someone like me I’d say you’d be good.

Also, I know you don’t like that you have to install the Failover Clustering Feature to all of the servers before you can create your cluster.  However please remember that unlike a pure hypervisor, Windows Server is an operating system that does many things for many people.  To install all of the possible features out of the box is a ridiculous notion – for one thing, it would triple the footprint and multiply exponentially the attack surface of Windows Server… to say nothing of having code running that you don’t need which takes resources.

To save time, I recommend the following PowerShell cmdlets:

Install-WindowsFeature –Name Failover-Clustering –IncludeManangementTools –ComputerName MyServer1
Install-WindowsFeature –Name Failover-Clustering –IncludeManangementTools –ComputerName MyServer2
Install-WindowsFeature –Name Failover-Clustering –IncludeManangementTools –ComputerName MyServer3
New-Cluster –Name MyCluster –Node MyServer1, MyServer2, MyServer3 –StaticAddress

(There are probably ways to wildcard that – -ComputerName * or something, but that is not the point of the article).

The point of this article is not to Mike’s article apart – for one thing, he is probably doing better on Microsoft technology than I would have when I was new to VMware, for another I have great respect for him, both as a person and as an IT Pro.  I just find it amusing that a VMware evangelist is struggling to learn Hyper-V and System Center, just as so many of the Microsoft evangelists have been struggling to learn VMware.  There is a huge learning curve to be sure… no matter which way you go.

While I am reasonably fluent and certified in both technologies, there is no question that I favour Microsoft… just as Mike favours VMware.  I am glad to see that he is trying to learn Microsoft though… even though some of the ways he is going about it may be questionable.

The one thing that I will point out though is that Mike is right… there are two ways of building a Microsoft Cluster – you can use the Failover Cluster Manager, or you can use System Center VMM.  Michael points out that these technologies would do well to communicate better.  I agree, and recommend that users pick one or the other.  I would also like to point out that in vCenter Server you can create a cluster, but if you are only using ESXi (Vmware’s hypervisor) without vCenter Server there is no way to create a cluster… the technology is simply not supported unless you pay for it.  Score one for Microsoft.

Mike, on a personal note, I would love to sit with you and show you the vastness of System Center and Microsoft’s Private Cloud one day.  Geography seems to work against us, as you are (I believe) in Scotland, and I am in Japan.  There is a catch though… I will gladly teach you Microsoft’s virtualization stack from top to bottom… but I want you to do the same for me with the vSphere stack.  I know the technology and am certified, but I would cherish the opportunity to relearn it from you, as I have followed your articles with reverence for many years.

If you ever do care to take me up on the offer Mike, my email address is  Drop me a line, we’ll figure it out.  I suspect that we would both be able to write some great articles following those sessions, and we would both have newfound respect for the other’s technology of choice.

Building the IT Camp with PowerShell Revisited

I always said I am not hard to please… I only need perfection.  So when I wrote my PowerShell script to build my environment the other day I was pleased with myself… until I realized a huge flaw in it.  Generation 1.

Actually to be fair, there is nothing wrong with Generation 1 virtual machines in Hyper-V; they have served us all well for several years.  However how could I claim to live on the bleeding edge (Yes, I have made that claim many times) and yet stay safe with Generation 1?

In the coming weeks Windows Server 2012 R2 will become generally available.  One of the huge changes that we will see in it is Generation 2 virtual machine hardware.  Some of the changes in hardware levels include UEFI, Secure Boot, Boot from SCSI, and the elimination of legacy hardware (including IDE controllers and Legacy NICs).

Of course, since Generation 1 hardware is still fully supported, we need to identify when we create the VM which Generation it will be, and this cannot later be changed.

I had forgotten about this, and when I created the script (of which I was quite proud) I did not think of this.  It was only a few hours later, as I was simultaneously installing nine operating systems, that I noticed in the details pane of my Hyper-V Manager that all of my VMs were actually Gen1.


Remember when I said a couple of paragraphs ago that the generation level cannot be changed?  I wasn’t kidding.  So rather than living with my mistake I went back to the drawing board.  I found the proper cmdlet switches, and modified my script accordingly.

As there is a lot of repetition in it, I am deleing six of the nine VMs from the list.  You are not missing out on anything, I assure you.

# Script to recreate the infrastructure for the course From Virtualization to the Private Cloud (R2).
# This script should be run on Windows Server 2012 R2.
# This script is intended to be run within the Boot2VHDX environment created by Mitch Garvis
# All VMs will be created as Generation 2 VMs (except the vCenter VM for which it is not supported).
# All VMs will be configured for Windows Server 2012 R2
# System Center 2012 R2 will be installed.

# Variables

$ADM = "Admin"                # VM running Windows 8.1 (for Administration)
$ADMMIN = 512MB                # Minimum RAM for Admin
$ADMMAX = 2GB                # Maximum RAM for Admin
$ADMVHD = 80GB                # Size of Hard Drive for Admin

$SQL = "SQL"                # VM (SQL Server)
$SQLMIN = 2048MB            # Minimum RAM assigned to SQL
$SQLMAX = 8192MB            # Maximum RAM assigned to SQL
$SQLCPU = 2                # Number of CPUs assigned to SQL
$SQLVHD = 200GB                # Size of Hard Drive for SQL

$VCS = "vCenter"             # VM (vSphere vCenter Cerver) (Windows Server 2008 R2)
$VCSMIN = 2048MB             # Minimum RAM assigned to vCenter
$VCSMAX = 4096MB             # Maximum RAM assigned to vCenter
$VCSCPU = 2                 # Number of CPUs assigned to vCenter
$VCSVHD = 200GB                # Size of Hard Drive for vCenter

$VMLOC = "C:\HyperV"            # Location of the VM and VHDX files

$NetworkSwitch1 = "CorpNet"        # Name of the Internal Network

$W81 = "E:\ISOs\Windows 8.1 E64.iso"            # Windows 8.1 Enterprise
$WSR2 = "E:\ISOs\Windows Server 2012 R2.iso"        # Windows Server 2012 R2
$W2K8 = "E:\ISOs\Windows Server 2008 R2 SP1.iso"     # Windows Server 2008 R2 SP1

# Create VM Folder and Network Switch
MD $VMLOC -ErrorAction SilentlyContinue
$TestSwitch1 = Get-VMSwitch -Name $NetworkSwitch1 -ErrorAction SilentlyContinue; if ($TestSwitch1.Count -EQ 0){New-VMSwitch -Name $NetworkSwitch1 -SwitchType Internal}

# Create & Configure Virtual Machines
New-VM -Name $ADM -Generation 2 -Path $VMLOC -MemoryStartupBytes $ADMMIN -NewVHDPath $VMLOC\$ADM.vhdx -NewVHDSizeBytes $ADMVHD -SwitchName $NetworkSwitch1
Set-VM -Name $ADM -DynamicMemory -MemoryMinimumBytes $ADMMIN -MemoryMaximumBytes $ADMMAX
Add-VMDvdDrive $ADM | Set-VMDvdDrive -VMName $ADM -Path $W81

New-VM -Name $SQL -Generation 2 -Path $VMLOC -MemoryStartupBytes $SQLMIN -NewVHDPath $VMLOC\$SQL.vhdx -NewVHDSizeBytes $SQLVHD -SwitchName $NetworkSwitch1
Set-VM -Name $SQL -DynamicMemory -MemoryMinimumBytes $SQLMIN -MemoryMaximumBytes $SQLMAX -ProcessorCount $SQLCPU
Add-VMDvdDrive $SQL | Set-VMDvdDrive -VMName $SQL -Path $WSR2

New-VM -Name $VCS -Path $VMLOC -MemoryStartupBytes $VCSMIN -NewVHDPath $VMLOC\$VCS.vhdx -NewVHDSizeBytes $VCSVHD -SwitchName $NetworkSwitch1
Set-VM -Name $VCS -DynamicMemory -MemoryMinimumBytes $VCSMIN -MemoryMaximumBytes $VCSMAX -ProcessorCount $VCSCPU
Set-VMDvdDrive -VMName $VCS -Path $W2K8

#Start Virtual Machines
Start-VM $ADM
Start-VM $SQL
Start-VM $VCS

In the script you can see a few differences between my original script (in the article) and this one.  Firstly on all machines that are running Windows 8.1 or Windows Server 2012 R2 I have set the switch –Generation 2.  That is simple enough.

Adding the virtual DVD was a little trickier; with Generation 1 hardware there was a ready IDE port for you to connect the .ISO file to.  In Gen 2 it is all about SCSI, so you have to use the Add-VMDvdDrive cmdlet, and then connect the .ISO file (Set-VMDvdDrive –VMName <Name> –Path <ISO Path>Not only for simplicity but also to demonstrate that you can I have put these two cmdlets on a single line, connected with a pipe (the | key).

I want to thank a couple of colleagues for helping me out with the Generation 2 hardware and DVD issues… especially Sergey Meshcheryakov , who was quick to answer.  The exact cmdlet switches were not easy to track down!

…and remember, if I can learn it, so can you!  Even the great Sean Kearney once did not know anything about PowerShell… and now look at him!

Creating a New AD Forest in Windows Server Core (Revisited)

Several years ago Steve Syfuhs and I sat down and figured out how to create a new Active Directory forest in Windows Server Core.  It was an interesting experience, and even though I later gave rights to that article to the Canadian IT Pro Team (at the time it was Damir Bersinic) when you search for the term ‘Create AD Forest Server Coremy article still comes up first.

R2 I have gotten a bit more adept with the command prompt of late (especially with my diving into Windows PowerShell recently, but even before), so when I had the need to create a new AD Forest for a courseware environment I am building, I decided to revisit this topic, and see what changes I could make.

In 2009 I had to create an answer file, or at least I believed I did.  It turns out that now I can get away with one command line string, which is as follows:

dcpromo /InstallDNS:yes /NewDomain:forest /

/DomainNetBIOSName:SKI /ReplicaOrNewDomain:domain /RebootOnCompletion:yes


For the record I had to break up the text into three lines, but obviously this should all be typed onto a single line.


The first time I ran this command it failed.  I suspect this is because I had a DHCP address assigned.  Before embarking on this trip, I suggest you assign a static IP address to your Server Core box.  While it is simpler to do it with the sconfig text-mode configuration menu tool, you can also use the following netsh command:

netsh interface ipv4 set address name=”Local Area Connection” source=static address= mask= gateway=

At this point you should be ready to go… remember that with Windows Server 2012 (and R2) once you have the OS installed it is easy to manage it remotely using either PowerShell or the Server Manager console.  Just make sure you have the right credentials, and you are good to go!

Building an IT Camp with PowerShell

I have been telling people for a couple of years that if they want to ensure a good future in the IT field there are two things to learn: System Center and PowerShell.  I unfortunately am quite good with one, but have been referring to myself as a scripting luddite for quite some time.  It is just something that I have not had the chance to learn.  After all, as a trainer and (Virtual) Evangelist I have not really had a lot of opportunity to get my hands on the type of environment where it would come in handy.

Recently I was in a conversation with a colleague who was complaining that he was too busy all of the time, and was really not enjoying his job because he hardly had time to breathe.  I asked him what sort of tasks he did on a regular basis, and when he told me my answer was simple: ‘If you have to do a task only once, do it manually.  If you might have to do it twice or more… automate it.’  In other words, learn PowerShell.

As I walked away from that meeting I realized that I was a hypocrite.  I built the labs for my course, From Virtualization to the Private Cloud, by hand, and every time I had to rebuild the environment I was doing it manually.  Considering the scope of what was involved I was not only being a hypocrite, I was being stupid.

Time is money, and time wasted is money lost.  I was scheduled to teach a four hour seminar on Hyper-V at the end of last week, and I decided that I was going to include some PowerShell management into that session.  I sat down and learned the basics, and that resulted not only in a better for the attendees last Friday, but also in an article titled Managing Hyper-V Virtual Machines with Windows PowerShell.  I started with some basics, how to start and stop VMs, how to check the VM memory, things like that.  I then expanded into creating a virtual machine, and adjusting the settings for it.  I was thrilled to be able to do all of this from the command line.

Okay, that was great, but now I needed to create a script that would really help me.  I knew there wouldn’t be anything on-line that would be exactly what I needed, but I was sure I would find the basics out there.  I found a great article by Neil Tucker on how he builds a couple of virtual machines for his course 50331 (Windows 7, Enterprise Desktop Support Technician).  Neil’s article gave me the basic framework for what I would come up with, including how to set variables for different VMs such as name, memory, and hard drive size.  It even went so far as to attach the proper ISO file to each VM and installs the OS using answer files.  As I already have my hard drives built I didn’t need that… but I was going to take things a little farther than Neil did.

I needed to build a script that would build nine virtual machines, each of which has its own special requirements.  I also needed to ensure that they would be connected to a virtual switch (which I would have to build as well if it wasn’t already there).

Although strictly speaking I do not need my script to create the VHDX files for me, I do want to make sure that each VM will connect to my pre-created virtual hard drive files, so I wrote the script to go through the motion of creating them in the correct place; I can then simply copy over them.

Up to now I have delivered the course on standard laptops (HP EliteBook 8570w with 32GB RAM).  However this likely would not be the case going forward, so it was important that I write the script so that I could easily provision new hardware with the course.


  1. Create a virtual switch for the course (check to see that it does not already exist)
  2. Create a repository for all course virtual machines and virtual hard disk files to reside
  3. Create nine virtual machines, each with their own settings for dynamic memory, CPUs.
  4. Connect all virtual machines to the virtual network switch
  5. (For extra credit) attach the appropriate OS DVD to each virtual machine
  6. Start all of the virtual machines.

While I thought about allowing the person running the script to choose their VM names, I decided that this would make it confusing for attendees running the courseware labs, where I have set the VM names appropriately.

Here is what I came up with:

# Script to recreate the infrastructure for the course From Virtualization to the Private Cloud (R2).
# This script should be run on Windows Server 2012 R2.
# This script is intended to be run within the Boot2VHDX environment created by Mitch Garvis
# All VMs will be configured for Windows Server 2012 R2 unless otherwise stated

# Variables

$ADM = “Admin”                # VM running Windows 8.1 (for Administration)
$ADMMIN = 512MB                # Minimum RAM for Admin
$ADMMAX = 2GB                # Maximum RAM for Admin
$ADMVHD = 80GB                # Size of Hard Drive for Admin

$DC1 = “DC1”                # VM (Domain Controller) (Windows Server Core)
$DC1MIN = 512MB                # Maximum RAM assigned to DC1
$DC1MAX = 2048MB            # Maximum RAM assigned to DC1
$DC1VHD = 30GB                # Size of Hard Drive for DC1

$SQL = “SQL”                # VM (SQL Server)
$SQLMIN = 2048MB            # Minimum RAM assigned to SQL
$SQLMAX = 8192MB            # Maximum RAM assigned to SQL
$SQLCPU = 2                # Number of CPUs assigned to SQL
$SQLVHD = 200GB                # Size of Hard Drive for SQL

$STOR = “Storage”            # VM (Storage Spaces, iSCSI Target)
$STORMIN = 512MB             # Minimum RAM assigned to Storage
$STORMAX = 2048MB             # Maximum RAM assigned to Storage
$STORVHD = 30GB                # Size of first Hard Drive for Storage
$STORVHD2 = 100GB            # Size of second Hard Drive for Storage
$STORVHD3 = 100GB            # Size of third Hard Drive for Storage

$VMM = “VMM”                # VM (System Center Virtual Machine Manager)
$VMMMIN = 2048MB             # Minimum RAM assigned to VMM
$VMMMAX = 8192MB             # Maximum RAM assigned to VMM
$VMMCPU = 2                 # Number of CPUs assigned to VMM
$VMMVHD = 100GB                # Size of Hard Drive for VMM

$OM = “OpsMgr”                # VM (System Center Operations Manager)
$OMMIN = 2048MB             # Minimum RAM assigned to OpsMgr
$OMMAX = 8192MB             # Maximum RAM assigned to OpsMgr
$OMCPU = 2                 # Number of CPUs assigned to OpsMgr
$OMVHD = 100GB                # Size of Hard Drive for OpsMgr

$ORC = “Orchestrator”             # VM (System Center Orchestrator)
$ORCMIN = 2048MB            # Minimum RAM assigned to Orchestrator
$ORCMAX = 8192MB             # Maximum RAM assigned to Orchestrator
$ORCCPU = 2                 # Number of CPUs assigned to Orchestrator
$ORCVHD = 100GB                # Size of Hard Drive for Orchestrator

$SM = “SrvMgr”                 # VM (System Center Service Manager)
$SMMIN = 2048MB             # Minimum RAM assigned to Service Manager
$SMMAX = 8192MB             # Maximum RAM assigned to Service Manager
$SMCPU = 2                 # Number of CPUs assigned to Service Manager
$SMVHD = 100GB                # Size of Hard Drive for Service Manager

$VCS = “vCenter”             # VM (vSphere vCenter Cerver) (Windows Server 2008 R2)
$VCSMIN = 2048MB             # Minimum RAM assigned to vCenter
$VCSMAX = 4096MB             # Maximum RAM assigned to vCenter
$VCSCPU = 2                 # Number of CPUs assigned to vCenter
$VCSVHD = 200GB                # Size of Hard Drive for vCenter

$VMLOC = “C:\HyperV”            # Location of the VM and VHDX files

$NetworkSwitch1 = “CorpNet”        # Name of the Internal Network

$W81 = “E:\ISOs\Windows 8.1 E64.iso”            # Windows 8.1 Enterprise
$WSR2 = “E:\ISOs\Windows Server 2012 R2.iso”        # Windows Server 2012 R2
$W2K8 = “E:\ISOs\Windows Server 2008 R2 SP1.iso”    # Windows Server 2008 R2 SP1

# Create VM Folder and Network Switch
MD $VMLOC -ErrorAction SilentlyContinue
$TestSwitch1 = Get-VMSwitch -Name $NetworkSwitch1 -ErrorAction SilentlyContinue; if ($TestSwitch1.Count -EQ 0){New-VMSwitch -Name $NetworkSwitch1 -SwitchType Internal}

# Create Virtual Machines
New-VM -Name $ADM -Path $VMLOC -MemoryStartupBytes $ADMMIN -NewVHDPath $VMLOC\$ADM.vhdx -NewVHDSizeBytes $ADMVHD -SwitchName $NetworkSwitch1
Set-VM -Name $ADM -DynamicMemory -MemoryMinimumBytes $ADMMIN -MemoryMaximumBytes $ADMMAX

New-VM -Name $DC1 -Path $VMLOC -MemoryStartupBytes $DC1MIN -NewVHDPath $VMLOC\$DC1.vhdx -NewVHDSizeBytes $DC1VHD -SwitchName $NetworkSwitch1
Set-VM -Name $DC1 -DynamicMemory -MemoryMinimumBytes $DC1MIN -MemoryMaximumBytes $DC1MAX

New-VM -Name $SQL -Path $VMLOC -MemoryStartupBytes $SQLMIN -NewVHDPath $VMLOC\$SQL.vhdx -NewVHDSizeBytes $SQLVHD -SwitchName $NetworkSwitch1
Set-VM -Name $SQL -DynamicMemory -MemoryMinimumBytes $SQLMIN -MemoryMaximumBytes $SQLMAX -ProcessorCount $SQLCPU

New-VM -Name $STOR -Path $VMLOC -MemoryStartupBytes $STORMIN -NewVHDPath $VMLOC\$STOR.vhdx -NewVHDSizeBytes $STORVHD -SwitchName $NetworkSwitch1
Set-VM -Name $STOR -DynamicMemory -MemoryMinimumBytes $STORMIN -MemoryMaximumBytes $STORMAX

New-VM -Name $VMM -Path $VMLOC -MemoryStartupBytes $VMMMIN -NewVHDPath $VMLOC\$VMM.vhdx -NewVHDSizeBytes $VMMVHD -SwitchName $NetworkSwitch1
Set-VM -Name $VMM -DynamicMemory -MemoryMinimumBytes $VMMMIN -MemoryMaximumBytes $VMMMAX -ProcessorCount $VMMCPU

New-VM -Name $ORC -Path $VMLOC -MemoryStartupBytes $ORCMIN -NewVHDPath $VMLOC\$ORC.vhdx -NewVHDSizeBytes $ORCVHD -SwitchName $NetworkSwitch1
Set-VM -Name $ORC -DynamicMemory -MemoryMinimumBytes $ORCMIN -MemoryMaximumBytes $ORCMAX -ProcessorCount $ORCCPU

New-VM -Name $OM -Path $VMLOC -MemoryStartupBytes $OMMIN -NewVHDPath $VMLOC\$OM.vhdx -NewVHDSizeBytes $OMVHD -SwitchName $NetworkSwitch1
Set-VM -Name $OM -DynamicMemory -MemoryMinimumBytes $OMMIN -MemoryMaximumBytes $OMMAX -ProcessorCount $OMCPU

New-VM -Name $SM -Path $VMLOC -MemoryStartupBytes $SMMIN -NewVHDPath $VMLOC\$SM.vhdx -NewVHDSizeBytes $SMVHD -SwitchName $NetworkSwitch1
Set-VM -Name $SM -DynamicMemory -MemoryMinimumBytes $SMMIN -MemoryMaximumBytes $SMMAX -ProcessorCount $SMCPU

New-VM -Name $VCS -Path $VMLOC -MemoryStartupBytes $VCSMIN -NewVHDPath $VMLOC\$VCS.vhdx -NewVHDSizeBytes $VCSVHD -SwitchName $NetworkSwitch1
Set-VM -Name $VCS -DynamicMemory -MemoryMinimumBytes $VCSMIN -MemoryMaximumBytes $VCSMAX -ProcessorCount $VCSCPU

# Configure Virtual Machines
Set-VMDvdDrive -VMName $ADM -Path $W81
Set-VMDvdDrive -VMName $DC1 -Path $WSR2
Set-VMDvdDrive -VMName $SQL -Path $WSR2
Set-VMDvdDrive -VMName $STOR -Path $WSR2
Set-VMDvdDrive -VMName $VMM -Path $WSR2
Set-VMDvdDrive -VMName $OM -Path $WSR2
Set-VMDvdDrive -VMName $ORC -Path $WSR2
Set-VMDvdDrive -VMName $SM -Path $WSR2
Set-VMDvdDrive -VMName $VCS -Path $W2K8

Start-VM $ADM
Start-VM $DC1
Start-VM $SQL
Start-VM $STOR
Start-VM $VMM
Start-VM $OM
Start-VM $ORC
Start-VM $SM
Start-VM $VCS

Please remember that until a little under a week ago I had not written a single script longer than a couple of lines.  While I am sure there are efficiencies that can be improved upon, I don’t think it’s too bad for a first go at it.

So now that I am scripting, what do you think you could come up with?  The way I see it, if I could do it… anyone can!

Managing Hyper-V Virtual Machines with Windows PowerShell

Warning: The following post was written by a scripting luddite.  The author readily admits that he would have difficulty coding his way out of a paper bag, and if the fate of the world depended on his ability to either write code or develop software then you had better start hoarding bottled water and cans of tuna.  Fortunately for everyone, there are heroes to help him!

I love the Graphical User Interface (GUI).  I use it every day in both the Windows client and Windows Server operating systems.  It makes my life easier on a day to day basis.

With that being said, there are several tasks that administrators must do on a regular basis.  There is no simple and reliable way to create repetitive task macros in the GUI.  Hence we can either work harder, or we can learn to use scripting tools like Windows PowerShell.

Along the way I have gotten some help from some friends.  Ed Wilson’s books have provided a wealth of information for me, and Sean Kearney has been my go-to guy when I need help.  There was a time when I was teaching a class and was asked ‘Can PowerShell do that?’  I replied by saying that if I asked Sean Kearney to write a PowerShell script to tie my shoes, I was reasonably sure he could do it because PowerShell can do ANYTHING.  Well one of my students posted that comment on Twitter, and got the following reply from Sean (@EnergizedTech):

Get-Shoe | Invoke-Tie

It makes sense too…because PowerShell works with a very simple Verb-Noun structure, and if you speak English it is easy to learn.

I may be a scripting luddite, but I do know a thing or two about virtualization, and especially Hyper-V.  So it only stands to reason that if I was going to start learning (and even scarier, teaching) PowerShell, I would start with the Hyper-V module.  As a good little Microsoft MVP and Community Leader, it only makes sense that I would take you along for the ride 🙂

Most of what can be done in PowerShell can also be done in the GUI.  If I want to see a list of the virtual machines on my system, I simply open the Hyper-V Manager and there it is.


PowerShell is almost as simple… Type Get-VM.


By the way you can filter it… if you only want virtual machines that start with the letter S, try:

Get-VM S*

One of the advantages of PowerShell is that it allows you to manage remote servers, rather than having to log into them you can simply run scripts against them.  If you have a server called SWMI-Host1, you can simply type:

Get-VM –Server SWMI-Host1

Starting and stopping virtual machines is simple…

Start-VM Admin


Again, your wildcards will work here:

Start-VM O*

This command will start all VMs that start with the letter O.

If you want to check how much memory you have assigned to all of your virtual machines (very useful when planning as well as reporting) simply run the command:

Get-VMMemory *


I did mention that you could use this command for reporting… to make it into an HTML report run the following:

Get-VMMemory * | ConvertTo-HTML | Out-File c:\VMs\MemReport.htm

To make it into a comma separated values (CSV) file that can easily be read in Microsoft Office Excel, just change the command slightly:

Get-VMMemory * | ConvertTo-CSV | Out-File c:\VMs\MemReport.csv

The report created is much more detailed than the original screen output, but not so much so as to be unusable.  See:

Making Changes

So far we have looked at VMs, we have started and stopped them… but we haven’t actually made any changes to them. Let’s create a new virtual machine, then make the changes we would make in a real world scenario.

New-VM –Name PSblog –MemoryStartupBytes 1024MB –NewVHDPath c:\VHDs\PSblog.vhdx –NewVHDSizeBytes 40GB –SwitchName CorpNet

With this simple script I created a virtual machine named PSblog with 1024MB of RAM, a new virtual hard disk called PSblog.vhdx that is 40GB in size, and connected it to CorpNet.

Now that will work, but you are stuck with static memory.  Seeing as one of the great features of Hyper-V is Dynamic Memory, let’s use it with the following script:

Set-VMMemory –VMName PSblog –DynamicMemoryEnabled $true –MinimumBytes 512MB –StartupBytes 1024MB MaximumBytes 2048MB

Now we’ve enabled dynamic memory for this VM, setting the minimum to 512MB, the maximum to 2048MB, and of course the startup RAM to 1024MB.

For the virtual machine we are creating we might need multiple CPUs, and because some of our hosts may be newer and other ones older we should set the compatibility mode on the virtual CPU to make sure we can Live Migrate between all of our Intel-based hosts:

Set-VMProcessor –VMName PSblog –Count 4 –CompatibilityForMigrationEnabled $true

At this point we have created a new virtual machine, configured processor, memory, networking, and storage (the four food groups of virtualization), and are ready to go.

I will be delving deeper into Hyper-V management with PowerShell over the next few weeks, so stay tuned!

NOTE: While nothing in this article is plagiarized, I do want to thank a number of sources, on whose expertise I have leaned rather heavily.  Brien Posey has a great series of articles on Managing Hyper-V From the Command Line on which is definitely worth reading.  He focuses on an add-on set of tools called the Hyper-V Management Library (available from so many of the scripts he discusses are not available out of the box, but the articles are definitely worth a read.  Rob McShinsky has an article on SearchServerVirtualization (a property) called Making sense of new Hyper-V 2012 PowerShell cmdlets which is great, and links to several scripts for both Server 2008 R2 and Server 2012.  Thanks to both of them for lending me a crutch… you are both worthy of your MVP Awards!

From Server Core to GUI to… MinShell?

This post was originally written for the Canadian IT Pro Connection blog, and can be seen there at

In Windows Server 2008 we were introduced to a revolutionary way to install Windows Server: Server Core.

Server Core may look boring – there’s nothing to it except the command prompt – but to an IT Pro it is really exciting for several reasons:

  • It requires fewer resources, so in a virtualization environment you can optimize your environment even more than previously;
  • It has a smaller attack surface, which makes it more secure;
  • It has a smaller patch footprint, which means less work for us on Patch Tuesdays; and
  • We can still use all of the familiar tools to manage it remotely, including System Center, MMC Consoles, and PowerShell.

imageDespite all of these advantages in my experience a lot of IT Pros did not adopt Server Core.  Simply states, they like the GUI (Graphical User Interface) manageability of the full installation of Windows Server.  Many do not like command lines and scripting, and frankly many are just used to the full install and did not want to learn something new.  I have even met some IT Pros who simply click the defaults when installing the OS, so they always ended up with the full install.

As you can see in this screenshot, the default installation is now Server Core. This is not done to confuse people, but going forward most servers are going to be either virtual hosts or virtual machines, and either way Server Core is (more often than not) a great solution.

Of course, if you do this and did not want Server Core you are still in good shape, because new in Windows Server 2012 you can add (or remove) the GUI interface on the fly.  You can actually switch between Server Core and Full (GUI) Install whenever you want, making it easier to manage your servers.

There are a couple of ways to install the GUI from the command prompt, although both use the same tool – DISM (Deployment Image Service Manager).  When you are doing it for a single (local) server, the command is:

Dism /online /enable-feature /featurename:ServerCore-FullServer /featurename:Server-Gui-Shell /featurename:Server-Gui-Mgmt

While the Dism tool works fine, one of the features that will make you want Windows Server 2012 on all of your servers now is the ability to manage them remotely, and script a lot of the jobs.  For that Windows PowerShell is your friend.  The script in PowerShell would be nearly as simple:

Import-Module Dism
Enable-WindowsOptionalFeature –online -Featurename ServerCore-FullServer,Server-Gui-Shell,Server-Gui-Mgmt


It takes a few minutes, but once you are done you can reboot and presto, you have the full GUI environment.

While that in and of itself is pretty amazing, we are not done yet.  There is a happy medium between Server Core and Full GUI.

MinShell (Minimum Shell) offers the administrator the best of both worlds.  You have the GUI management tools (Server Manager) but no actual GUI, which means that you are still saving the resource, have a smaller attack surface, less of a patch footprint, AND full manageability!

imageWhat the product development team has done is simple: they made the GUI tools a Server Feature… in fact, they made it three separate features (see graphic).  Under User Interfaces and Infrastructure there are three options that allow the server administrator to customize the visual experience according to his needs.

The Graphical Management Tools and Infrastructure is the Server Manager, along with the other GUI tools that we use every day to manage our servers.  It also includes the Windows PowerShell Integrated Scripting Environment (ISE) which allows administrators an easier to create and manage their PowerShell scripts.

The Desktop Experience gives the administrator the full desktop experience – similar to the Windows 8 client OS – including features such as Picture and Video viewers.

The Server Graphical Shell is exactly that: the GUI.  In other words we can turn the GUI on or off by using the Add Roles and Features Wizard (and the Remove Roles and Features Wizard).

Now there are a number of catches to remember:

First of all when you go down to MinShell the Add Roles and Features Wizard is still available, but not in Server Core.  Make sure you have this article on hand if you do go down to Server Core.

Next, if you install the full GUI and then remove the components then re-adding them isn’t a problem; however if you install the Server Core installation from the outset then the GUI (and Management) bits are not copied to the drive, which means that if you want to add them later you will need to have the installation media handy.

While hard drive space is pretty cheap, and it is easy to decide to install the full GUI every time and then remove it (so that the bits will be there when you want them).  However remember that with Hyper-V in Windows Server 2012 the limits are pretty incredible, and it is entirely possible that you will have up to 1,024 VMs on a host; that means that the few megabytes required for the GUI bits could add up.

Whether you opt for the Server Core, Full GUI, or the MinShell compromise, Windows Server 2012 is definitely the easiest Server yet to manage, either locally or remotely, one-off commands or scripts.  What I expect admins will be most excited about is the choices.  Run your servers your way, any way!

Hyper-V on the Client: How to install the hypervisor on Windows 8

For four years people have known me as the Hyper-V guy, and of course my interest in Microsoft virtualization dates back to 2004.  However I am also known as a Windows client guy – my MVP Award category is Windows Expert (IT Pro).  So what could be better than combining the two?  Microsoft has given me the high-tech equivalent to Reese’s Peanut Butter Cups!

Of course, we all know how to install Hyper-V in Windows Server… just use the Add Roles Wizard.  As that is not an option in the client, it is slightly different.  Here you go, step by step:

  • SNAGHTML4b439You need to open the Windows Features screen.  There are two ways to do that.  The first is from the Control Panel, click on Programs and then Turn Windows features on or off.  For those of us who like to use the direct commands you can click Windows Key-R to open the Run box, and then type appwiz.cplThis will open the Programs and Features window.  the option to Turn Windows features on or off is in the navigation pane.

In previous versions of Windows you could manage remote Hyper-V instances by downloading the Remote Server Administration Tools (RSAT) from Microsoft.  Since Hyper-V is now included in the operating system, so are the management tools.  From this screen we see that we have the option to simply install the Hyper-V Management Tools and you are off to the races – nothing has changed.  (the two sub-options are Hyper-V GUI Management Tools and Hyper-V Module for Windows PowerShell)

  • Once you select the Hyper-V Platform Windows will check to make sure your system supports it – of course, it is a 64-bit only option, and virtualization has to be enabled in the BIOS – and then installs the role.  It only takes a few seconds, and then you will get the screen asking you to reboot.

As it is in Server, installing Hyper-V requires multiple reboots (see my article titled ‘Layer 1 or Layer 2 Hypervisor? A common misconception of Hyper-V, and a brief explanation of the Parent Partition’) but because of the greatly improved boot time of Windows 8 that takes less than a minute (even in my Multi-OS, Boot-to-VHD system).  Once you are back in, the Metro Start screen has two new tiles:


As you see, the Hyper-V Manager and the Hyper-V Virtual Machine Connection tool are there and ready to go.  You can start creating and booting up VMs, as well as connecting to VMs both locally and remotely.

Remember, if you are going to manage or connect to remote systems, you will have a much better experience with domain-joined clients.  The security is still managed by certificates.

Now that we’ve got Hyper-V in the client, what are you waiting for people? Virtualize!