Manage Learn to apply best practices and optimize your operations.

Using PowerShell to manage Microsoft Hyper-V

Windows admins aren't limited when it comes to managing Hyper-V from the command line. Here are two (free) options for supporting virtual machines in Windows.

Many admins use PowerShell to automate components like user creation and folder permissions, but virtualization technologies can also be managed from the command line, including Microsoft Hyper-V.

While there are several ways to manage Hyper-V with PowerShell, this article will focus on the free approaches using Windows Management Instrumentation (WMI) scripting and an open source tool from CodePlex.

Before using WMI scripting to manage Hyper-V, it’s important to understand what classes are available. Microsoft’s list includes a significant number of classes and while is fairly complete, they are not necessarily easy to use and are certainly not intuitive. Therefore, using WMI to manage Hyper-V is not for the faint of heart.

One of the more popular methods for managing Hyper-V with PowerShell is with PowerShell Management Library for Hyper-V (PSHyperV) a free, open source CodePlex project written by James O’Neil. This is by far the best free option out there and gives administrators a very thorough collection of cmdlets that do everything from virtual machine inventory to virtual network management. Let’s touch on a few of them:

Get-VM -- returns all the virtual machines on a given Hyper-V server (see Figure 1).

Figure 1: Get-VM command (click to enlarge)

The following code demonstrates the Get-VM command:

Function Get-VM
{# .ExternalHelp MAML-VM.XML
       [parameter(ValueFromPipeLine = $true)] 
       $Name = "%",

       $Server = ".", #May need to look for VM(s) on Multiple servers
   Process {
       # In case people are used to the * as a wildcard... 
       if ($Name.count -gt 1 ) {[Void]$PSBoundParameters.Remove("Name")
; $Name | ForEach-object {Get-VM -Name $_ @PSBoundParameters}}
       if ($name -is [String]) {
          $Name = $Name.Replace("*","%")
          # Note in V1 the test was for caption like "Virtual%" which
did not work in languages other than English. 
          # Thanks to Ronald Beekelaar - we now test for a processID ,
the host has a null process ID, stopped VMs have an ID of 0. 
          $WQL = "SELECT * FROM MSVM_ComputerSystem WHERE ElementName
LIKE '$Name' AND ProcessID >= 0"

          if ($Running -or $Stopped -or $Suspended) {
            $state = ""
             if ($Running) {$State += " or enabledState = " +
[int][VMState]::Running }
             if ($Stopped) {$State += " or enabledState = " +
[int][VMState]::Stopped }
             if ($Suspended) {$State += " or enabledState = " +
[int][VMState]::Suspended }
             $state = $state.substring(4) 
             $WQL += " AND ($state)" 
          Get-WmiObject -computername $Server -NameSpace $HyperVNamespace -Query $WQL | Add-Member -MemberType ALIASPROPERTY -Name "VMElementName" -Value "ElementName" -PassThru 
       elseif ($name.__class) {
          Switch ($name.__class) {
             "Msvm_ComputerSystem"      {$Name}
             "Msvm_VirtualSystemSettingData"      {get-wmiobject -
computername $Name.__SERVER -namespace $HyperVNamespace -Query
"associators of {$($name.__path)} where
             Default       get-wmiobject -
computername $Name.__SERVER -namespace $HyperVNamespace -Query
"associators of {$($Name.__path)} where
resultclass=Msvm_VirtualSystemSettingData" |
{$_.getRelated("Msvm_ComputerSystem")} | Select-object -unique }

As you can see, the code basically wraps the WMI class with some helper logic and reports the results.

Get-VMSwitch -- Returns all the virtual switches on the Hyper-V server (see Figure 2).

Figure 2: Get-VMSwitch command (click to enlarge)
”Get-VMSwitch The following code demonstrates the Get-VMSwitch command:

Function Get-VMSwitch
{# .ExternalHelp MAML-VMNetwork.XML
       [parameter(ValueFromPipeline = $true)][Alias("Name")]

       $Server = "." #Can query multiple servers for switches
   process {
       Get-WmiObject -computerName $server -NameSpace $HyperVNamespace
-query "Select * From MsVM_VirtualSwitch Where elementname like '$VirtualSwitchname' "

Get-VMSnapShot -- Provides all the snapshots on the Hyper-V server (see Figure 3).

Figure 3: Get-VMSnapShot command (click to enlarge)

The following command demonstrates the Get-VMSnapShot command:

Function Get-VMSnapshot
{# .ExternalHelp MAML-VMSnapshot.XML
       [parameter(Position=0 , ValueFromPipeline = $true)]
       $VM = "%",


       $Server="." ,
          if ($VM -is [String]) {$VM=(Get-VM -Name $VM -Server $server) }
          if ($VM.count -gt 1 ) {[Void]$PSBoundParameters.Remove("VM") ; $VM |
ForEach-object { Get-VMSnapshot -VM $_ @PSBoundParameters}} 
          if ($vm.__CLASS -eq 'Msvm_ComputerSystem') {
             if ($current) {Get-wmiobject -computerNam $vm.__server -
Namespace $HyperVNamespace -q "associators of {$($vm.path)} where assocClass=MSvm_PreviousSettingData"}
             else {$Snaps=Get-WmiObject -computerName $vm.__server -NameSpace $HyperVNameSpace -Query "Select * From MsVM_VirtualSystemSettingData Where systemName='$($' and 
instanceID <> 'Microsoft:$($' and elementName like '$name' " 
                if ($newest) {$Snaps | sort-object -property 
creationTime | select-object -last 1 } 
                elseif ($root) {$snaps | where-object {$_.parent -eq
                $null} }
                else {$snaps}

PSHyperV includes several additional functions to help admins perform related tasks, including finding, manipulating and configuring different components of the hypervisor and can be found on the CodePlex website.

Writing WMI wrappers and using PSHyperV are just a few of the ways admins can manage Hyper-V using PowerShell. Note that the latest release of PSHyperV isn’t a complete version, and thus, isn’t as stable as other options may be.

You can follow on Twitter @WindowsTT.

Miss a column? Check out our Scripting School archive.

Brandon Shell has been in the IT industry since 1994. He started out as a PC tech and general fix-it guy for numerous companies. In 2007, he joined the PowerShell MVP ranks, and Shell has spent the past several years building his PowerShell knowledge and helping others build theirs.

Dig Deeper on Windows administration tools