Managing Hyper-V with PowerShell in Windows Server 2012

In this article we’ll look at how to manage the Hyper-V role in Windows Server 2012 using PowerShell 3.0. This feature is new in Windows Server 2012, as the Windows Server 2008 R2 version of Hyper-V didn’t have an integrated PowerShell module.

In Windows Server 2012 there has been extensive development in the PowerShell area. With all modules in the operating system there are now about 2,400+ cmdlets available to manage everything. The Hyper-V module alone consists of 164 cmdlets, but you will also use other cmdlets when automating your Hyper-V virtualization platform.

If you are totally new to Hyper-V, I would recommend that you fire up the Hyper-V Manager and look around in that and see what you can do and what the default settings look like.  A bit later in this post we will look at how we can automate some of these features. Everything in the Hyper-V Manager can be accessed and managed from the PowerShell console, but not everything fits into this article.


To show what PowerShell Hyper-V cmdlets are available you can use the following command:

Get-Command –Module Hyper-V

And if you want to count them you can use the following:

(Get-Command –Module Hyper-V).Count

PowerShell help is your friend! With it you can find what parameters can be used and see examples of the cmdlet usage:

Get-Help Get-VM –Full

Activating Hyper-V on Windows 2012

In order to use the Hyper-V module in PowerShell we need to enable that feature. Note that you do not need to activate the Hyper-V role in order to use the PowerShell module, but you need to use it against a remote Hyper-V host:

Add-WindowsFeature Hyper-V –IncludeManagementTools

This requires a restart because you have enabled the Hyper-V role. If you want to check what Hyper-V features are enabled on the server. simply type the following: Get-WindowsFeature Hyper*



After we have enabled the role we need to do some initial configuration. To be able to see and manage Hyper-V, we have to run the PowerShell Console as Administrator. Star by right-clicking on the PowerShell icon in the start menu.



If you do not use an elevated console you should see the following:



If you do have an elevated console we can actually see some values, as shown below.



Now, there are two locations where the virtual machines and virtual hard disks are stored in Hyper-V that we want to change from the original location. These locations are:


C:\Users\Public\Documents\Virtual Hard Disks

This only comes into action if you create VMs and do not specify a particular path. But it is quite important: Say, for instance, you don’t have a huge system drive. If you create large virtual machines the disk space will run out, the virtual machines will pause, and the Hyper-V host will not be able to write any more files, which can lead to an outage. Using snapshots can also fill up your system drive if you do not configure the virtual machine path properly, as the snapshots are stored in the aforementioned path by default. (In a future article we’ll play with virtual machine snapshots.)

So let’s configure the paths to a non-system drive using PowerShell:

PS C:\Windows\system32> Set-VMHost -VirtualHardDiskPath D:\VMs -VirtualMachinePath D:\VMs

If you want to configure five hosts at the same time you can do this:

PS C:\Windows\system32> “HV01”,”HV02”,”HV03”,”HV04”,”HV05” | %{ Set-VMHost –ComputerName $_ -VirtualHardDiskPath D:\VMs -VirtualMachinePath D:\VMs}

Let’s configure networking with PowerShell next. There are three different switch types; typically you want the external one. It is only with the external switch type that you can have virtual machines reaching other networks and machines on remote hosts.

The parameter –AllowManagemetOS creates a virtual switch on the physical NIC called “PhysicalNic1Internal,” on which a virtual network adapter is created for the Hyper-V host to use for management traffic.

PS C:\Windows\system32> New-VMSwitch -Name Internal -AllowManagementOS $true -NetAdapterName “PhysicalNic1Internal”

Creating and Removing Virtual Machines

After these essential things has been configured, we can continue to create virtual machines and start them. Now we want to create five test virtual machines with the same configuration but with different virtual hard drives and names.

The first example creates five test virtual machines in the above default path without any virtual hard drive:

PS C:\Windows\system32> 1..5 | %{New-VM -Name “TestVM$_” -NoVHD -MemoryStartupBytes 256MB -SwitchName Lan}

If we add the parameter –Path and instead of –NoVHD and use –NewVHDPath and –NewVHDSizeBytes we will get virtual machines in nice folders with a system.vhdx virtual hard disk that is dynamic and can grow to 10 GB.

PS C:\Windows\system32> 1..5 | %{New-VM -Name “TestVM$_” -Path d:\VMs -NewVHDPath “d:\VMs\TestVM$_\System.vhdx” -NewVHDSizeBytes 10GB -MemoryStartupBytes 512MB -SwitchName Lan}

Perhaps you noticed that I did not specify more than just the parent path in the virtual machine path, but it still created those folders and a virtual machine subfolder where the configuration xml file lies.

To start these VMs after they’ve been created, we can use PowerShell pipelining:

PS C:\Windows\system32> 1..5 | %{New-VM -Name “TestVM$_” -Path d:\VMs -NewVHDPath “d:\VMs\TestVM$_\System.vhdx” -NewVHDSizeBytes 10GB –MemoryStartupBytes 512MB -SwitchName Lan} | Start-VM

As you can see, it is quite easy to create just a few or hundreds of virtual machines. And you can create them – using PowerShell — without having go through a wizard for each and every one of them!

It is almost as easy to remove the virtual machines as it is to create them. The following command requires that the virtual machines are turned off: Get-VM TestVM* | Remove-VM -Force

The only problem with this cleaning is that it leaves folders and virtual hard disks behind. If I am using a cmdlet that says Remove-VM, I want it to actually remove everything. So, with a small addition we can achieve this anyway: If we omit the TestVM* portion, it will clean out the whole host of virtual machines registered there. (Hopefully you have a backup somewhere!) See the command below:

Get-VM TestVM* | %{ Stop-VM -VM $_ -Force; Remove-VM -vm $_ -Force ; Remove-Item -Path $_.Path -Recurse -Force}