Windows PowerShell has been gradually gaining in prominence for the past few years, but the release of PowerShell 3.0 with Windows Server 2012 really kicked PowerShell into high gear. Microsoft added 2,300 new cmdlets to Server 2012. More than 160 of them enable you to manage Hyper-V. Prior to Server 2012 and PowerShell 3.0, you had to use either the Hyper-V cmdlets that were part of Microsoft System Center Virtual Machine Manager (VMM) or CodePlex's PowerShell Management Library for Hyper-V. With Server 2012, PowerShell 3.0 has effectively eliminated the need to use the Hyper-V cmdlets in VMM or the CodePlex library. (Note that if you're running PowerShell 3.0 on Windows 8, Windows Server 2008 R2, or Windows Server 2008, that's not the case. You still need to use the Hyper-V cmdlets in VMM or the CodePlex library.)

To see the entire list of new cmdlets for Hyper-V, check out TechNet's Hyper-V Cmdlets in Windows PowerShell web page. If you're using Server 2008 R2 or Server 2008, you might want to read the Windows IT Pro article "PowerShell Basics: System Requirements" or TechNet's Installing Windows PowerShell web page to see how you can install PowerShell 3.0 on older Windows releases.

Managing Hyper-V with PowerShell

You can install and manage Hyper-V using the GUI or PowerShell. With PowerShell, you can accomplish most of the tasks that you can accomplish with the GUI.

Before you can begin managing Hyper-V with PowerShell or the GUI, you need to make sure the Hyper-V role isinstalled on the Server 2012 systems you want to use as virtualization hosts. You can install the Hyper-V role using Server Manager, or you can install it with the PowerShell command:

Install-WindowsFeature -Name Hyper-V `
  -ComputerName ORPORTHV3 -IncludeManagementTools -Restart

This command installs the Windows Feature named Hyper-V on the computer named ORPORTHV3. When running this command, make sure that you include the -IncludeManagementTools parameter. This will install the Hyper-V Manager and the PowerShell module for Hyper-V.

Afterward, you can use the Get-Command cmdlet with the -Module Hyper-V parameter to see the available cmdlets for the Hyper-V module:

Get-Command -Module Hyper-V

Figure 1 shows an excerpt from the list of available cmdlets.

Listing the Available Hyper-V Cmdlets

Before jumping feet first into managing Hyper-V with PowerShell, it's good to get a couple of basics down. One of the most important basics is knowing how to use PowerShell's built-in Help files. They explain the functions of all the different cmdlets, provide their parameters, and even show usage examples.

If you're just getting started with PowerShell and Hyper-V, it's a good idea to download the latest Help updates from Microsoft. To update the Help files for the Hyper-V module, you need to use an elevated command prompt by starting PowerShell with the Run as administrator option and entering an administrative privileges account. Then, run the command:

Update-Help -Module Hyper-V

After updating your local Help files, you can get help on any of the Hyper-V cmdlets using the PowerShell Get-Help cmdlet. For example, the following command displays the full Help file for the Get-VM cmdlet:

Get-Help Get-VM -Full

If you want to see some examples of how to use the Hyper-V Get-Host cmdlet, you specify that cmdlet and include the -Examples parameter:

Get-Help Get-Host -Examples

Listing Hyper-V Hosts and Virtual Machines

You probably have already set up your Hyper-V host and created a number of virtual machines(VMs) on it. If you want to display the local Hyper-V host and its VMs, you can use the following two commands:

Get-VMHost
Get-VM

This will produce results similar to those in Figure 2. As you can see, the Get-VMHost cmdlet displays the name of the Hyper-V host, how many logical processors it has, its memory capacity, and whether live migration is enabled. The Get-VM cmdlet displays the VMs on the local Hyper-V host as well as their current state, CPU usage, assigned memory, uptime, and status. Both cmdlets let you obtain this information from a remote host. You just need to use the -ComputerName parameter.

Using the Get-VM and Get-VMHost Cmdlets

PowerShell cmdlets return objects and not just text. This lets you dig into the properties of each VM. For example, you can pipe the Get-VM cmdlet's output to the Format-List cmdlet, like this:

Get-VM -Name ORPORTVM1 | Format-List *

As this command demonstrates, you can use the Get-VM cmdlet to list the attributes of a specific VM by including the -Name parameter followed by the name of the VM in which you're interested. In this case, a VM named ORPORTVM1 is retrieved as an object, which is piped to Format-List. This cmdlet then displays all the properties of that object. Figure 3 shows some of those properties.

Piping the Get-VM Cmdlet's Output to the Format-List Cmdlet

If you use the Select-Object cmdlet, which has the built-in alias of select, you can dig deeper and look at the specific settings for each property. For instance, to display the configuration of a VM's network adapters, you can dig deeper into the NetworkAdapters property, which is actually a collection of network configuration settings, using a command such as:

Get-VM -Name ORPORTVM1 |
  select -ExpandProperty NetworkAdapters |
  select VMName, SwitchName, IPAddresses

This command pipes the ORPORTVM1 object to the first Select-Object cmdlet, which uses the -ExpandProperty parameter to select and expand theNetworkAdapters property. The results are then piped to the second Select-Object cmdlet. As you can see in Figure 4, the second Select-Object cmdlet selects and displays the VM name, virtual switch name, and IP addresses.

Using the Get-VM Cmdlet to Display the Networking Characteristics of a Local VM

The power that PowerShell offers as a management tool goes beyond what's offered by the Hyper-V console. Unlike the Hyper-V GUI, PowerShell lets you perform repeatable scripted actions. And unlike the Hyper-V GUI, where you can work on only one VM at a time, PowerShell lets you easily expand your management tasks across several VMs with a single command. For example, the following command shows how you can use Get-VM in conjunction with piping and the Select-Object cmdlet to dig deep and display the VM name, virtual switch name, and IP addresses for all the VMs on the local host:

Get-VM | select -ExpandProperty NetworkAdapters |
  select VMName, SwitchName, IPAddresses

Figure 5 shows the results. As you can see, most of the VMs are using dynamically assigned IP addresses, whereas WS2012Full is using a static address.

Using the Get-VM Cmdlet to Display the Networking Characteristics of All the Local VMs

Although digging into the Get-VM cmdlet's results can return specific information about a VM, including its network configuration, a more direct way of obtaining a VM's networking configuration is to use the Get-VMNetworkAdapter cmdlet, like this:

Get-VMNetworkAdapter -VMName ORPORTVM1

In this command, the Get-VMNetworkAdapter cmdlet's -VMName parameter specifies the VM from which to retrieve the network information. You can see the results of this command in Figure 6. (More information about using PowerShell to work with VM networking settings will be presented later.)

Using the Get-VMNetworkAdapter Cmdlet to Display the Networking Characteristics of a Local VM

Managing Virtual Machines

After listing the VMs and learning how to display their properties, probably the next Hyper-V management task that you'll want to learn how to do is create VMs. Using PowerShell to create VMs lets you easily standardize the VMs and their configurations. For example, here's how you can create anew Hyper-V VM using the New-VM cmdlet:

New-VM -Name "MyNewVM" -MemoryStartupBytes 512MB `
  -SwitchName "External Virtual Network" `
  -NewVHDPath "C:\MS Hyper-V VMs\MyNewVM.vhdx" `
  -NewVHDSizeBytes 20GB

The new VM will be named MyNewVM. It'll have 512MB of memory and a virtual network adapter that uses a virtual switch named External Virtual Network. The new VM will use the default Hyper-V VM path. (If you want to use a different path for the VM configuration, you can use the optional -Path parameter.) The VM will have a dynamically expanding Virtual Hard Disk (VHDX) in the location specified by the -NewVHDPath parameter.

The New-VM cmdlet doesn't haveparameters that let you specify the number of virtual processors or whether the VM can use dynamic memory. So, if you want to increase the number of virtual processors or use dynamic memory, you need to use the Set-VMProcessor and Set-VMMemory cmdlets, like this:

Set-VMProcessor "MyNewVM" -Count 2
Set-VMMemory "MyNewVM" -DynamicMemoryEnabled $true

After these commands run, the VM named MyNewVM will have two virtual processors and use dynamic memory.

You can start and stop VMs using the Start-VM and Stop-VM cmdlets. The following commands start, then stop MyNewVM:

Start-VM "MyNewVM"
Stop-VM "MyNewVM"

Before the VM can actually perform any useful tasks, it needs a guest OS. You can't directly install a guest OS with PowerShell, but you can automate the install by using an ISO file containing the guest OS, a Virtual Floppy Disk (VFD), and an autounattend.xml file. The virtual floppy drive can be added to the VM before it starts and the VM must be configured to boot from the VFD. The VFD can contain the autounattend.xml file, which is essentially an answer file that allows unattended installation of the Windows OS. The autounattend.xml file points to an ISO image that can be accessed by the guest VM. You can find more information about creating autounattend.xml files in the TechNet guide "Step-by-Step: Basic Windows Deployment for IT Professionals." You can find a more detailed example of how this works in the sidebar "Handy Hyper-V PowerShell Scripts."

Handy Hyper-V PowerShell Scripts

Here are four Windows PowerShell scripts that might come in handy when managing your Hyper-V environment:

CreateVM.ps1. Creating a fully functional virtual machine (VM) in PowerShell is a multi-step process. This script first creates a vanilla VM, then optionally installs the guest OS. To run the guest OS installation portion of this script, you must have an ISO image of the guest OS that you want to install and you need to create an autounattand.xml file. When the VM starts, it boots from the ISO image and the Windows setup program reads the setup responses from the autounattend.xml file. Windows setup implicitly searches for the answer file on the attached drives (e.g., virtual floppy drive). For more information about creating unattended setup answer files, see the TechNet guide "Step-by-Step: Basic Windows Deployment for IT Professionals." After creating the autounattended.xml file, you need to create a virtual floppy drive, mount it to a VM, and copy the autounattended.xml file to the root of the drive.

PromptLiveMigration.ps1. There might be times when you just want to quickly move multiple VMs using live migration. Instead of going into Hyper-V Manager and selecting them one at a time, you can use the PromptLiveMigration.ps1 script to fire off one or more live migrations. This script prompts you for the VMs on the local host. You can then select the VM that you want to migrate.

GetVMUptime.ps1. VM uptime information is displayed by Hyper-V Manager, but it's off to the side, where you don't usually see it. In addition, it's difficult to quickly see which VMs have been active the longest. The GetUptime.ps1 script quickly reports on the uptime of the VMs currently running on your local Hyper-V host. It lists the VMs and their uptime, putting the VMs that have been active the longest at the top of the list.

FindWhichVMHasDVD.ps1. If you have several VMs on a single host and one of the VMs has the DVD drive that you want to use, it can be a tiresome undertaking finding out which VM owns that DVD drive. With Hyper-V Manager, you'd need to check the settings of every VM. The FindWhichVMHasDVD.ps1 script quickly interrogates the DVD status of all the VMs and optionally lets you release the DVD drive if it's already in use.

You can download these four scripts by clicking the Download button near the top of the page. You'll need to remove the .txt extensions before using them. If you want to run the CreateVM.ps1 script, you'll also need to customize several variable values. The script's comments tell you where those customizations are needed. All the scripts have comments that describe how they work.

One of the features that makes PowerShell such an effective management tool is the fact that you can use it to perform multiple actions with a single command. For example, using the Start-VM and Stop-VM commands with the wildcard character (*) enables you to start and stop multiple VMs simultaneously. The following commands show how to start and stop all the VMs that begin with the characters OR:

Start-VM OR*
Stop-VM OR*

In addition to starting and stopping VMs, you can use the Restart-VM cmdlet to reboot a VM. You can also use the Suspend-VM cmdlet to pause a VM and the Resume-VM cmdlet to get it running again. Like the Start-VM and Stop-VM cmdlets, the Suspend-VM and Resume-VM cmdlets accept the VM name as a parameter. They can also take advantage of the wildcard character to act on multiple selected VMs.

You can delete existing VMs by using the Remove-VM cmdlet, as shown here:

Remove-VM "MyNewVM"

PowerShell can also work with VM snapshots, which you can use to restore your VMs to an earlier state. You can create snapshots of your VMs using the Checkpoint-VM cmdlet. For example, the following command pipes the results of the Get-VM OR* command to the Checkpoint-VM cmdlet to create snapshots for the VMs whose names begin with OR:

Get-VM OR* | Checkpoint-VM

Creating snapshots for a large number of VMs can take a while. If you need to regularly take snapshots of many VMs, you might consider adding the -AsJob parameter to run the snapshot process in the background.

To list all the different snapshots, you can use the Get-VMSnapshot cmdlet. The following example shows how to list all the snapshots for the VMs whose names begin with OR:

Get-VM "OR*" | Get-VMSnapshot

You can see the results in Figure 7.

Using the Get-VMSnapshot Cmdlet to List All the Snapshots for the VMs Whose Names Begin with OR

Managing VHDs

The previous section demonstrated how to create a VHDX at the same time as the VM. However, you can also create VHDXsand Virtual Hard Disks (VHDs) separately from VMs so that you can add them to existing VMs or populate your VMM library. The following example shows how to create a VHDX file that has a maximum size of 127GB:

New-VHD -Path "C:\MS Hyper-V VMs\MyNewDynamicVHDX.vhdx" `
  -SizeBytes 127GB

Although they require more physical disk space, fixed VHDs and VHDXs provide somewhat better performance than their dynamic counterparts. You can create fixed VHDs and VHDXs by adding the -Fixed parameter. For example, here's how to create a new fixed VHDX named MyNewFixedVHDX.vhdx that's 20GB in size:

New-VHD -Path "C:\MS Hyper-V VMs\MyNewFixedVHDX.vhdx" `
  -Fixed -SizeBytes 20GB

Differencing disks are useful in lab, Help desk, and test scenarios. They're the lowest performing option, but they also require less disk space that the other types of VHDs and VHDXs. You can create a differencing VHDX using the options shown here:

New-VHD `
  -ParentPath "C:\MS Hyper-V VMs\MyNewParentVHDX.vhdx" `
  -Path "C:\MS Hyper-V VMs\MyNewDiffVHDX.vhdx" -Differencing

If you want to add a VHD or VHDX to an existing VM, you need to use the Add-VMHardDiskDrive cmdlet. The following example shows how you can add a VHDX named MyNewDynamicVHDX.vhdx to the VM named MyNewVM:

Add-VMHardDiskDrive -VMName "MyNewVM" `
  -Path "C:\MS Hyper-V VMs\MyNewDynamicVHDX.vhdx"

Oddly, there's no Hyper-V PowerShell cmdlets to delete VHDs and VHDXs. However, you can delete them using the standard Remove-Item cmdlets. The following command shows how to delete a VHDX:

Remove-Item "C:\MS Hyper-V VMs\MyNewFixedVHDX.vhdx"

Managing Virtual Switches and Virtual Network Adapters

In addition to working with VMs, VHDs, and VHDXs, PowerShell can create and manage virtual switches and virtual network adapters. Hyper-V supports three types of virtual switches: external, private, and internal. External virtual switches connect to your corporate network through the host's network adapter. Private and internal virtual switches are used only by VMs within the host. The private virtual switch only allows VMs to connect to other VMs. The internal virtual switch allows VMs to connect to other VMs and allows the host to connect to VMs.

Because the private and internal virtual switches don't communicate with the outside world, very little information is required to create a new one—essentially just the switch's name and type. For example, to create a private virtual switch, you use the New-VMSwitch cmdlet with the -SwitchType parameter set to Private:

New-VMSwitch "MyNewPrivateSwitch" -SwitchType Private `
  -Notes "Private virtual switch"

Creating an external virtual switch is somewhat more involved because you need to connect the switch to one of the host's network adapters. To get the names of the host's network adapters, you can use the Get-NetAdapter cmdlet, like this:

Get-NetAdapter -Name * | Format-List `
  -Property Name, InterfaceDescription, InterfaceName

In this example, the Get-NetAdapter command is retrieving information from all the network adapters. The output is then piped to the Format-List cmdlet, which extracts each adapter's Name, InterfaceDescription, and InterfaceName properties. In Figure 8, you can see that there are three host adapters listed. Two are physical adapters, and one is a virtual adapter used by an external virtual switch.

Using the Get-NetAdapter Cmdlet to Get the Names of the Host's Network Adapters

To create a new external virtual switch, you need to use the value found in the Name property. For example, here's how to create new external switch named MyNewExternalSwitch that uses the host network adapter named Local Area Connection:

New-VMSwitch -Name "MyNewExternalSwitch" `
  -NetAdapterName "Local Area Connection" `
  -AllowManagementOS $true

The -AllowManagementOS parameter is important because it specifies whether the parent partition will be allowed to access the physical network adapter. The value of $true permits parent partition access.

You can use the Get-VMSwitch cmdlet to list the different virtual switches that have been created on the Hyper-V host. Like most of the other cmdlets, you can use the -Name parameter and wildcards to restrict the values returned by the cmdlet. If you use the Get-VMSwitch cmdlet with no parameters, as you can see in the following example, it'll return all the virtual switches on the Hyper-V host:

Get-VMSwitch

Figure 9 shows sample results. As you can see, there are two different virtual switches configured on the local Hyper-V host. Like their names suggest, External Virtual Network is an external virtual switch and MyNewPrivateSwitch is a private virtual switch.

Using the Get-VMSwitch Cmdlet to Return All the Virtual Switches on the Hyper-V Host

Although the virtual switch is a mechanism for connecting VMs to each other or for connecting VMs to the outside world, the VMs must have a virtual network adapter to take advantage of the virtual switches. To add a virtual network adapter, you can use the Add-VMNetworkAdapter cmdlet. For example,here's a command that adds a new virtual network adapter to the VM named MyNewVM and connects that adapter to the private virtual switch named MyNewPrivateSwitch:

Add-VMNetworkAdapter -VMName "MyNewVM" `
  -SwitchName "MyNewPrivateSwitch"

The virtual network adapter will be named Local Area Connection, in accordance with the standard Windows naming convention. If your organization has a naming standard for your virtual network adapters, you can use the optional -Name parameter to explicitly name the virtual network adapter.

Like you might expect, you can use the Remove-VMSwitch and Remove-VMNetworkAdapter cmdlets to delete existing virtual switches and virtual network adapters. It's worth noting that you can't delete VM assets that are currently in use.

Performing Live Migrations

You can use PowerShell to initiate Hyper-V live migrations. In case you're unfamiliar with live migration, it's a Hyper-V technology that essentially lets you move Hyper-V VMs between hosts with no end user downtime. Before you can use live migration, you need to make sure that it's enabled. Live migration must be enabled on all of the different Hyper-V hosts that will participate in the live migration process. You can check this with the Get-VMHost cmdlet discussed previously. If live migration isn't enabled, you can enable it using the command:

Enable-VMMigration

In addition to enabling live migration on the host, the VMs themselves must be configured in such a way that each host can access all of the VMs' assets. For more information about configuring Hyper-V for live migration in a shared storage environment, check out the Windows IT Pro article "Windows Server 2012: Shared Storage Live Migration." You can learn more about setting up shared nothing live migration in the Windows IT Pro article "Shared-Nothing VM Live Migration with Windows Server 2012 Hyper-V."

After all the Hyper-V hosts and VMs have been configured for live migration, you can use the Move-VM cmdlet to perform a live migration. For example, if you want to move the VM named ORPORTVM1 to the Hyper-V host named WS2012-N2, you'd use the command:

Move-VM -Name ORPORTVM1 -DestinationHost WS2012-N2

Move-VM uses the default live migration network. To specify the default live migration network, you need to use the Set-VMMigrationNetwork cmdlet. The following example shows how to set up live migration to use the network that has the subnet address of 192.168.100.1:

Set-VMMigrationNetwork 192.168.100.1

The Move-VM cmdlet supports wildcard characters to manage multiple VMs. You can also set the number of simultaneous live migrations that can be performed. The default setting allows for two concurrent live migrations. You can alter the limit for simultaneous live migrations using the command:

Set-VMHost -MaximumVirtualMachineMigrations 4

In this example, the maximum number of concurrent live migrations is being set to four on the local Hyper-V host.

Bring Your Hyper-V Management Capabilities to the Next Level

The graphical Hyper-V management console is great for ad-hoc administration and one-off type tasks. However, when you need to perform repetitive tasks, work with multiple VMs, or provide VM reports, PowerShell provides the commands, tools, and efficiency to bring your management capabilities to the next level. Although I couldn't cover the entire gamut of Hyper-V management tasks that you can perform with PowerShell here, I hope that I've given you an idea of the breadth of PowerShell's management capabilities as well as several useful examples to help you get started managing Hyper-V with PowerShell.