Automated Hyper-V VM snapshots with PowerShell

In this blogpost I will share a script to automate Hyper-V VM snapshots with PowerShell. My goal of this script is to properly shutdown the virtual machine and create a snapshot and maintain the configured amount of snapshots based on day’s. This way I can reduce storage and it is possible to revert to a specific snapshot if the machine has broken down.

Basic information

We need some basic information that is stored in three variables. These variables contains the Hyper-V host name, the virtual machine name listed on the host and the amount of snapshots you want to maintain based on day’s.

$VirtualMachine = "My-VM"
$HyperVHost = "HVhost.lab.local"
$SnapshotDays = 10

Note: The virtual machine name can be listed by running this Powershell command Get-VM -CompterName $HyperVHost or just check in the Hyper-V Manager.

Shutdown virtual machine

in the first section we want to make sure the virtual machine is off. This is done by the Stop-VM which initiates a proper shutdown. Before we provide the command we first check if the virtual machine is running.

# Get VM information
$VM = Get-VM -ComputerName $HyperVHost -Name $VirtualMachine
# Provide shutdown command
IF ($VM.State -ne "Off") 
{
	Write-Host (Get-Date)": Shutdown $VirtualMachine"
	Stop-VM -ComputerName $HyperVHost -Name $VirtualMachine
}

Wait until virtual machine is off

The next step is to wait until the virtual machine is off and that is done by the following loop.

# Wait until VM is off
Write-Host (Get-Date)": Waiting for $VirtualMachine to be Off"

While ((Get-VM -ComputerName $HyperVHost -Name $VirtualMachine).State -ne "Off")
{
	Write-Host "." -NoNewLine
	Start-Sleep -Seconds 5
}

Write-Host " "
Write-Host (Get-Date)": $VirtualMachine is Off"

Creating the snapshot

When the virtual machine is off the snapshot is taken. The format I used is the name of the virtual machine with the date of the taken snapshot.

Write-Host (Get-Date)": Creating snapshot of $VirtualMachine"
$DateFormat = Get-Date -Format yyyy.MM.dd
$Snapshot = $VM.Name + "-" + $DateFormat

CheckPoint-VM -ComputerName $HyperVHost -Name $VirtualMachine -Snapshotname $Snapshot 
Start-Sleep -Seconds 2

Removing the old snapshots

This is done by collecting the snapshots older then the configured day’s. After these are collected the snapshots are removed by the Remove-VMSnapshot command.

Write-Host (Get-Date)": Removing snapshots of $VirtualMachine older than $SnapshotDays"

Remove-VMSnapshot (Get-VMSnapshot -ComputerName $HyperVHost -VMName $VirtualMachine | Where-Object {$_.CreationTime -lt (Get-Date).AddDays(-$SnapshotDays)})

Starting the virtual machine

The last action is to power on the virtual machine. This is done by the Start-VM command.

Write-Host (Get-Date)": Starting $VirtualMachine"
Start-VM -ComputerName $HyperVHost -Name $VM.Name

Write-Host (Get-Date)": Backup script done"

The complete script

$VirtualMachine = "My-VM"
$HyperVHost = "HVhost.lab.local"
$SnapshotDays = 10

# Get VM information
$VM = Get-VM -ComputerName $HyperVHost -Name $VirtualMachine
# Provide shutdown command
IF ($VM.State -ne "Off") 
{
	Write-Host (Get-Date)": Shutdown $VirtualMachine"
	Stop-Computer -ComputerName $VirtualMachine -Force
}

# Wait until VM is off
Write-Host (Get-Date)": Waiting for $VirtualMachine to be Off"

While ((Get-VM -ComputerName $HyperVHost -Name $VirtualMachine).State -ne "Off")
{
	Write-Host "." -NoNewLine
	Start-Sleep -Seconds 5
}
Write-Host " "
Write-Host (Get-Date)": $VirtualMachine is in Off state"

Write-Host (Get-Date)": Creating snapshot of $VirtualMachine"
$DateFormat = Get-Date -Format yyyy.MM.dd
$Snapshot = $VM.Name + "-" + $DateFormat

CheckPoint-VM -ComputerName $HyperVHost -Name $VirtualMachine -Snapshotname $Snapshot 
Start-Sleep -Seconds 2

Write-Host (Get-Date)": Removing snapshots of $VirtualMachine older than $SnapshotDays"

Remove-VMSnapshot (Get-VMSnapshot -ComputerName $HyperVHost -VMName $VirtualMachine | Where-Object {$_.CreationTime -lt (Get-Date).AddDays(-$SnapshotDays)})

Write-Host (Get-Date)": Starting $VirtualMachine"
Start-VM -ComputerName $HyperVHost -Name $VM.Name

Write-Host (Get-Date)": Backup script done"

Create a scheduled task that will run the script at a time you want and the snapshots are going to be created. I have scheduled the task to run every night at 3.00 AM so there are no interruptions on the server during production time.

I hope this is helpful for you and if you have any questions please leave a comment below.