Save to My DOJO
While the Hyper-V management console is cozy and can certainly get the job done, I think there are a handful of PowerShell cmdlets that can make your life easier. At least in terms of managing Hyper-V. These are commands that have a graphical counterpart, although sometimes it takes a little work to get to it. These are my top 10 cmdlets every Hyper-V pro should know, but in no particular order. All of these commands have help files so be sure to check them out as well. All references are to Hyper-V cmdlets that run on PowerShell 3.0.
1. Get-VM
I’d have to say the one command used the most is Get-VM. It does exactly what its name implies as you can see in Figure 1.
Figure 1
Remember that what you are seeing are virtual machine objects and there is more than this default display.
Figure 2
As you can see, you can get virtual machines by name. Or you can filter on any of the virtual machine parameters. For example, I usually only want to see running virtual machines so I can use a command like this.
PS C:> get-vm | where {$_.state -eq 'running'} | sort Uptime | select Name,Uptime,@{N="MemoryMB";E={$_.MemoryAssigned/1MB}},Status
I even went ahead and sorted on the Uptime property and formatted the assigned memory as MB. You can see the results in Figure 3.
Figure 3
Want to get to know Get-VM better? Have a look at our Deep Dive into Get-VM
2. Start-VM
Of course seeing a virtual machine is one thing. Controlling them is equally important. Starting a virtual machine couldn’t be any easier.
PS C:> start-vm chi-win8
If it will take some time to start the VM or if you are starting many of them, you can use the –AsJob parameter to push the task to the background.
PS C:> start-vm jdh* -asjob
3. Stop-VM
On the flipside, stopping a virtual machine is just as easy. PowerShell once again makes it much easier when dealing with multiple virtual machines.
PS C:> stop-vm jdh*
The shutdown is made through the guest operating system. If the VM has open applications or unsaved data, it will wait 5 minutes before shutting down, unless the operating system shows the screen is locked. You can always force the shutdown with the –Force parameter. In worse case situations you can tell the cmdlet to simply kill power to the virtual machine.
PS C:> stop-vm "XP Lab" –turnoff
The other option you have is to stop the virtual machine but put it in a saved state.
PS C:> stop-vm chi-win8 –save –force
4. Checkpoint-VM
Use the Checkpoint-VM to create a snapshot for a given virtual machine. It is as easy as this:
PS C:> checkpoint-vm -VMName "XP Lab"
But with PowerShell this makes it much easier to snapshot a number of machines with a single command, something you can’t really do in the graphical console.
PS C:> get-vm chi* | checkpoint-vm -SnapshotName "Weekly Snapshot $((Get-Date).toshortdatestring())" –AsJob
With this single command I’m getting all virtual machines that start with CHI and creating a snapshot called “Weekly Snapshot” that includes today’s date. Because this might take a little time to complete I’m running the tasks as background jobs.
[optin-monster-shortcode id=”lwzgfpb294pntqna”]
5. Get-VMSnapshot
If you have VM snapshots, you will most likely want to manage them. Here’s a great situation where the PowerShell cmdlet is your friend. First, what are all the snapshots I currently have?
PS C:> get-vmsnapshot *
Figure 4
You can get all snapshots for a given VM.
PS C:> get-vm "fp01" | get-vmsnapshot
Figure 5
Or a specific snapshot:
PS C:> get-vm chi-fp01 | get-vmsnapshot -Name weekly*
Figure 6
6. Remove-VMSnapshot
Of course, you will want to periodically delete old snapshots which is where Remove-VMSnapshot comes in handy. Let’s say a week or two has passed and I want to clean up the previously created snapshots. Here’s my single line PowerShell command.
PS C:> get-vm chi* | Get-VMSnapshot -Name "weekly snapshot 4/20/2013" | Remove-VMSnapshot –whatif
As you can see in Figure 7, the –WhatIf parameter allows me a chance to double-check what I’m about to do.
Figure 7
To actually remove the snapshots all I need to do is re-run the command omitting the –Whatif parameter.
7. Test-VHD
I find Test-VHD quite handy in performing periodic validation of VHD and VHDX files. This cmdlet should detect if there is a potential problem with a VHD such as if a differencing chain has been broken. The cmdlet returns True if everything is ok. You can check multiple files at once:
PS C:> dir F:VHD | test-vhd True True True True True True
Although, if one of these failed I wouldn’t necessarily know which one. Instead I might try something like this:
PS C:> dir G:VHDs | Select Name,@{n="Test";Expression={ Test-VHD $_.fullname}} | sort Test
You can see the results in Figure 8.
Figure 8
8. Export-VM
I’ve written about Export-VM in the past to export a machine to disk. This command will export the virtual machine configuration, a copy of the VHD/VHDX files as well as any snapshots. Just make sure the destination doesn’t contain a folder with the same name as your virtual machine or the command will fail. Because this can take some time to run, I recommend using the –AsJob parameter. I can export a single machine:
PS C:> export-vm "test rig" -Path E:BackupFolder –asjob
Or multiple machines:
PS C:> export-vm jdh* -Path e:backupfolder -AsJob
9. Get-VMHost
This cmdlet provides information about the server, or in my case desktop, running Hyper-V.
Figure 9
The cmdlet has a –Computername parameter so you can connect to remove Hyper-V servers.
10. Get-VMNetworkAdapter
Lastly, I find Get-VMNetworkAdapter very useful because it helps me discover the IP addresses my virtual machines are running.
PS C:> Get-VMNetworkAdapter -VMName chi-dc04
Figure 10
Or to just get the addresses for this VM, I can run a command like this:
PS C:> Get-VMNetworkAdapter -VMName chi-dc04 | Select -expand IPAddresses
Figure 11
It isn’t that much more work to display all the IP v4 addresses for my currently running virtual machines.
PS C:> get-vm | where { $_.state -eq 'running'} | get-vmnetworkadapter | Select VMName,SwitchName,@{Name="IP";Expression={$_.IPAddresses | where {$_ -match "^172."}}} | Sort VMName
Figure 12
Try doing that in GUI!
Summary
The graphical Hyper-V management console is fine for simple and one-off type tasks. But when you want to work with multiple virtual machines at once or dive deeper into a virtual machine configuration say for reporting purposes, then there really is no substitute for starting with these 10 cmdlets. I’m confident that as you work with these you’ll discover a few more cmdlets that will make your life much easier.
Not a DOJO Member yet?
Join thousands of other IT pros and receive a weekly roundup email with the latest content & updates!
30 thoughts on "10 Awesome Hyper-V Cmdlets"
Hey, I am a fan of your posts and I just want to point you to my blog and a couple of powershell scripts I have created them from a hodge podge of sites and just trial and error, not a programmer just old school administrator
http://stephanco.blogspot.com/2013/05/detailed-report-of-your-hyper-v-server.html this creates text file report of the vhost and vm’s
http://stephanco.blogspot.com/2013/05/new-vm-powershell-commandlet-to-easily.html this is an easy way to create vm’s from powershell, easy to use and easy to understand
Thank you for sharing those scripts with us James!
I created a new project called pshvm.codeplex.com and it is the first all powershell script free hyper-v manager that includes a replacement for vmconnect and mstsc. It is meant to be run from the console. I included my reporting.codeplex.com project so now you can manage and report for free. It can even create VM’s with just a few clicks and answering a few questions.
Hi. Am looking to script to list all VMs in SC Virtual Machine Manager, and their Maximum disk size but struggling to get this right.
This is my current thinking, but need guidance please…
get-vm | select name,$_.VirtualHardDisk.MaximumSize
Thanks
I don’t have SCVMM so I don’t know if those cmdlets are a little different. Using they Hyper-V module, I can do something like this.
Get-VM | Select Name,@{Name=”MaxSizeGB”;Expression={ (Get-VHD $_.id)[0].Size/1GB}}
This will get the first hard drive for each VM, which is usually the primary drive. Or if you wanted to enumerate all drives you might try something like this:
Get-VM CHI* | Foreach {
$_.HardDrives | Select VMName,Path,Controller*,@{Name=”MaxSizeGB”;Expression={ (Get-VHD $_.path)[0].Size/1GB}}
}
That said, if by chance the Get-VM cmdlet you are using with SCVMM is a little different, see if this gets you closer. I’m making an educated guess as to the syntax.
get-vm | select name,@{Name=”MaximumSize”;Expression={ $_.VirtualHardDisk[0].MaximumSize}}
I’m assuming the VirtualHardDisk property is a collection of disk objects and that you want the first one.
Hi, I am looking to list all the checkpoint avhdx for a VM. Get vhd list only active chain vhds. For other created checkpoints can we get the avhdx list.
Thanks
Soumen
Not sure I completely follow but would something like this work: get-vm MYVM| get-vmsnapshot | Get-VMHardDiskDrive | select VMName,Path
Hi Jeffrey,
Your articles are great and have helped me out a lot and made me realise how good PS is!
Never been great at scripting and I’m trying to combine two HV PS commands together but failing..wondered if you could help me. It’s probably very simple!
Basically I want to get all IP/VLAN info re vms so I’m trying to use get-vmnetadapter and get-vmnetadaptervlan and select just vmname,ipaddresses,vlanlist running on one command but my select statement only shows info from the second command after the pipe:
Get-VMNetworkAdapter PAHMGMT | Get-VMNetworkAdapterVlan | select vmname,switchname,ipaddresses,accessvlanid
Hi Jeffrey,
Ignore my last commend, I’ve sorted it, using this:
get-vm -vmname *| where {$_.state -eq ‘running’} | Get-vmnetworkadapter | Select vmName, ipaddresses,switchname, @{Name= “VLAN ID”; Expression={(Get-vmnetworkadaptervlan $_.vmname).accessvlanid}}
Hello Darren,
Check out the script that will help you to get the list of all Virtual Machines in Virtual Machine Manager and enumerate all their virtual drives.
http://charbelnemnom.com/2015/01/get-the-list-of-all-vms-in-virtual-machine-manager-and-their-virtual-disks-vmm-scvmm-hyperv-powershell/
Cheers,
-Charbel
Hi
i have multiples snapshot ;How to remove juste the first one (In time)
(sorry for my Anglish)
Get-VMSnapshot -VMName MYVM| Sor-object -property CreationTime | Select-Object -first 1 | Remove-VMSnapshot
Thanks a lot for those explanations!
I have got a question:
My Microsoft Hyper-V Server is running and I created a first VM and assigned some GB to it.
I can start it and everything, but I am wondering about this:
cant I control this VM directly from said Microsoft Hyper-V Server?
So that some window for the VM opens?
Thanks a lot,
Matthias
I’d suggest installing the Hyper-V Management tools on your desktop.Then use the VMConnect utility.
Hello!
I want to delete one of the vhdx associated with a VM. In the script I have the vhdx file captured as an object into $VHD
$VHD = Get-VHD -Path “$VHDPath$VHDFile” -ComputerName $VMHost
Is it possible to remove the VHD by the following command?
Remove-VMHardDiskDrive -VMHardDiskDrive $VHD
Did you try? You might also try: $VHD | Remove-VMHardDisk
Hi Jeffery,
I am having fun & games trying to use variables for looping through snaps and deleting them. 🙁
Manually I can execute the PS cmdlets no problem, like this example:
get-vm pt-SQL | Get-VMSnapshot -Name ‘pt-sql – (2015-07-13 – 11:48:32 AM_Shelveset54132_DesignerPerformance)’| Remove-VMSnapshot
But when I add a variable for that VMSnapshot name Powershell does not understand it. Here’s a sample:
### Decide which snaps you need deleted and replace the variable entries &Snaps and $SnapName – NB very important to het the correct snap name!
$VM = (‘pt-sql’,’pt-agent1′)
Write-Host $VM
$VMsnap = (“‘pt-sql”,”‘pt-agent1″)
Write-Host $
foreach ($VMsnap in $VMsnap)
{
$SnapName= “$VMsnap – (2015-07-13 – 11:48:32 AM_Shelveset54132_DesignerPerformance)'”
Write-Host $SnapName
}
###At this point all works as expected – I am doing Write-Host on the variables just to confirm the entries correlate.
###Then the next command fails with ‘Get-VMSnapshot : Unable to find a snapshot with given criteria.’ error..
$snapshot = get-vm $VM | Get-VMSnapshot –Name $SnapName
I have tried converting the snap name variable ToString or [String] thinking maybe it is the string conversion but that does not make any difference.
So to recap, what I am trying to do is create variables for my VM names and Snaps so that when I do maintenance I can automate removing a bunch of snaps across multiple VM’s. I think I am on the sort of right track here but I can’t figure out why Powershell does not accept the names for the snaps.
What am I doing wrong?
I think you need to move the $snapshot=… line into the foreach loop. You are looping through and resetting the value of $snapname every time. This isn’t a good place for code debugging. If you are still stuck, I encourage you to use the forums at PowerShell.org.
Hi there,
I’ve got a little problem. When I want to power off VM, so I type “Stop-VM “name of VM”…After this command, I have to confirm it, but I don’t want it. So I type “Stop-VM “name of VM” -Confirm:$false but happened the same. Waiting for confirmation.
Please, anybody, do you know, what am I supposed to do?
Did you try: Stop-VM MYVM -force
Hello Jeffery,
I’m trying to automate a shutdown of a multi-VM host environment from one computer. Basically I need this computer to get a shutdown command from our UPS that will tell it to run a Powershell. That Powershell them must stop all of the VMs that are on various hosts on our network (we have about 10 hosts).
It’s kind of asking a lot, but how would I be able to manipulate these commands to remote hosts?
Thanks.
First, read the help and examples for Stop-VM. You should be able to to feed in parameter values to a command like: Stop-VM -name VM1 -computername VMSERVER1
I use this function to quickly check our 7 VM servers and the VMs on them. It’s part of my profile.ps1 and already has an array built of $VM_SERVERS to iterate.
Function checkVMs
{Write-Output “Virtual Machine Server Statuses:”
invoke-command -computername $VM_SERVERS -ScriptBlock {get-vm|select ComputerName,Name,Uptime,CPUUsage,Status}|select ComputerName,Name,Uptime,CPUUsage,Status|sort ComputerName,Name|ft -AutoSize
Write-Output “Virtual Machine Snapshot Statuses:”
invoke-command -computername $VM_SERVERS -ScriptBlock
{get-vmsnapshot *|select ComputerName,VMName,SnapshotType,Name}|select ComputerName,VMName,SnapshotType,Name|sort Computername,VMName|ft -Autosize}
Hi Jeffery , 10x alot gr8 info, I’m looking for away to find all vhd files thats not used
in order to free space from my Lune.
thanks in advanced.
Hi Rafi,
There are a few ways you could implement this by running a PowerShell script. One way would be to query every VM and create a list of VHD files associated with every VM. Compare this list with all VHDs to find those which are not used. You could also check when each VHD file was last changed to ensure that it has not recently been accessed.
Thanks,
Symon Perriman
Altaro Editor