Taking a snapshot–via PowerShell [Hyper-V]
This week I am going to be sharing a bunch of scripts that show you how to interact with virtual machine snapshots in Hyper-V. And I am going to start off with the hardest one – taking a snapshot:
# Function for handling WMI jobs / return values
Function ProcessResult($result, $successString, $failureString)
{
#Return success if the return value is "0"
if ($result.ReturnValue -eq 0)
{write-host $successString}
#If the return value is not "0" or "4096" then the operation failed
ElseIf ($result.ReturnValue -ne 4096)
{write-host $failureString " Error value:" $result.ReturnValue}
Else
{#Get the job object
$job=[WMI]$result.job
#Provide updates if the jobstate is "3" (starting) or "4" (running)
while ($job.JobState -eq 3 -or $job.JobState -eq 4)
{write-host $job.PercentComplete "% complete"
start-sleep 1
#Refresh the job object
$job=[WMI]$result.job}
#A jobstate of "7" means success
if ($job.JobState -eq 7)
{write-host $successString
return $true}
Else
{write-host $failureString
write-host "ErrorCode:" $job.ErrorCode
write-host "ErrorDescription" $job.ErrorDescription
return $false}
}
}
# Prompt for the Hyper-V Server to use
$HyperVServer = Read-Host "Specify the Hyper-V Server to use (enter '.' for the local computer)"
# Prompt for the virtual machine to use
$VMName = Read-Host "Specify the name of the virtual machine"
# Prompt for the name of the new snapshot
$SnapshotName = Read-Host "Specify the name of the new snapshot"
# Get the management service
$VMMS = gwmi -namespace root\virtualization Msvm_VirtualSystemManagementService -computername $HyperVServer
# Get the virtual machine object
$VM = gwmi MSVM_ComputerSystem -filter "ElementName='$VMName'" -namespace "root\virtualization" -computername $HyperVServer
# Take the snapshot
$result = $VMMS.CreateVirtualSystemSnapshot($VM)
# Process the results
$snapshotSucceeded = ProcessResult $result "The snapshot was taken." "Failed to take snapshot."
# If the snapshot is created - rename it
if ($snapshotSucceeded)
{
# Get the job object from the results
$job2=[WMI]$result.job
# Get the snapshot that is assocated with the completed job
$newSnapshot = $job2.GetRelated("Msvm_VirtualSystemSettingData") | select -first 1
# Change the "ElementName"
$newSnapshot.ElementName = $SnapshotName
# Apply the changes to the snapshot
$result2 = $VMMS.ModifyVirtualSystem($VM, $newSnapshot.GetText(1))
# Check to see if renaming the snapshot succeeds
$renameSucceeded = ProcessResult $result2 "The new snapshot was renamed." "Failed to rename the new snapshot."
}
The tricky part of this script is not actually taking the snapshot (which is done with CreateVirtualSystemSnapshot) but naming the snapshot after it is taken (Hyper-V always auto-generates a snapshot name for you – and you need to rename it if you want to have a custom snapshot name). Actually, that isn’t hard either – the hard bit is *finding* the snapshot after it is taken in order to name it.
The secret here is that the new snapshot object (in WMI) will actually be associated with the job object once the snapshot is complete. So this script waits for the snapshot job to complete, then it gets the related system setting data from the completed job, and uses that to rename the snapshot. Once you have figured this bit out – the rest is quite straight forward.
Cheers,
Ben
Comments
- Anonymous
December 08, 2013
The comment has been removed - Anonymous
July 27, 2014
Hi, I got an error when executing the Script, my environment is Windows Server 2012 R2 + Windows Powershell ISE , and the error log is as follows: >>>>>>>>>>>>>>>>>>>>>>> Method invocation failed because [System.Management.ManagementObject] does not contain a method named 'CreateVirtualSystemSnapshot'. At C:UsersAdministratorDesktopPS-HyperVtest.ps1:52 char:1
- $result = $VMMS.CreateVirtualSystemSnapshot($VM)
-
+ CategoryInfo : InvalidOperation: (CreateVirtualSystemSnapshot:String) [], RuntimeException + FullyQualifiedErrorId : MethodNotFound >>>>>>>>>>>>>>>>>>>>>> Thank you
Anonymous
November 07, 2014
The comment has been removedAnonymous
April 17, 2015
The -namespace for Server 2012 "rootvirtualization" has changed to "rootvirtualizationv2" in Server 2012 R2Anonymous
August 23, 2016
Just desire to say your article is as amazing.The clarity in your post is simply cool and i could assume you are an expert on this subject. Well with your permission allow me to grab your feed to keep updated with forthcoming post. Thanks a million and please keep up the enjoyable work.