#requires -version 3.0 <# These commands require the Hyper-V module and appropriate permissions This is not a script to run from start to finish but a series of commands that demonstrate key steps in converting a snapshot to a virtual machine. **************************************************************** * DO NOT USE IN A PRODUCTION ENVIRONMENT UNTIL YOU HAVE TESTED * * THOROUGHLY IN A LAB ENVIRONMENT. USE AT YOUR OWN RISK. * * DO NOT USE IT OUTSIDE OF A SECURE, TEST SETTING. * **************************************************************** #> #not really necessary in PowerShell 3 because of auto-loading Import-Module Hyper-V #Testing with the local server $Server = $env:COMPUTERNAME <# Path to store exports. This will be created if it doesn't exist. It is relative to the server. #> $ExportPath = "E:\Exports" #name of VM to export $VMName= "Test Rig" #snapshot name, which will be name of imported VM as well $SnapName= "$VMName Clone" #region create the snapshot #create the snapshot with a custom name. This will use the default path for snapshots $snapshot = Checkpoint-VM -Name $VMName -SnapshotName $SnapName -ComputerName $Server -Passthru #this is what you get $snapshot #endregion #region Export the snapshot to disk #the snapshot has computer information so export is ON the server $export = Export-VMSnapshot -VMSnapshot $snapshot -Path $ExportPath -Passthru #$export is a snapshot object $export #here are the exported files dir E:\Exports -Recurse #endregion #region create new VM re-using exported disk #use values from snapshot $clone = New-VM -Name $snapshot.Name -NoVHD -MemoryStartupBytes $snapshot.MemoryStartup -switch "Private Data" -ComputerName $Server #add hard drives using the exported drives, not the ones in the path ForEach ($drive in $Snapshot.HardDrives) { #I want to use the exported disk files not the ones the snapshot points to. $VHD = Split-Path -leaf ($drive.path) #construct the path to the Virtual Hard Disk Folder and #the path to what should be the boot drive $VHDPath = Join-Path (Join-Path (Join-Path $ExportPath $VMName) "Virtual Hard Disks") $VHD #define a hash table for Add-VMHardDiskDrive parameters $addDriveHash=@{ VMName=$Clone.Name Path=$VHDPath ControllerType=$drive.ControllerType ControllerNumber=$drive.ControllerNumber ControllerLocation=$drive.ControllerLocation Computername=$Server } #The parameters to be passed to Add-VMHardDiskDrive $addDriveHash Add-VMHardDiskDrive @addDriveHash } #foreach drive #adjust VM with settings from snapshot #create a hashtable of snapshot values to apply to the clone $paramhash=@{ MemoryStartupBytes=$snapshot.MemoryStartup ProcessorCount=$snapshot.ProcessorCount Notes="Cloned $(Get-Date)" Name=$($clone.Name) Computername=$Server } if ($snapshot.DynamicMemoryEnabled) { $paramhash.Add("DynamicMemory",$snapshot.DynamicMemoryEnabled) $paramhash.Add("MemoryMinimumBytes",$snapshot.MemoryMinimum) $paramhash.Add("MemoryMaximumBytes",$snapshot.MemoryMaximum) } #add other settings as needed Set-VM @paramhash #the final result Get-VM $clone.name -ComputerName $Server | Select * #endregion #region import snapshot as new VM #modify XML configuration if you want to change the name. $VMPath = Join-Path (Join-Path $ExportPath $VMName) "Virtual Machines" $VMConfigPath = (dir $vmpath -filter *.xml).FullName #should be only one xml file [xml]$config = Get-Content -Path $VMConfigPath #rename snapshot name if you want $config.configuration.properties.name.'#text'="My Cloned VM" #save the config file $config.Save($VMConfigPath) <# #If running this remotely these commands can be done via a remoting session. $sb = { $VMPath = Join-Path (Join-Path $using:ExportPath $using:VMName) "Virtual Machines" $VMConfigPath = (dir $using:vmpath -filter *.xml).FullName [xml]$config = Get-Content -Path $VMConfigPath $config.configuration.properties.name.'#text'="My Cloned VM" #save the config file $config.Save($VMConfigPath) } Invoke-Command $sb -computername $Server #> #import the snapshot #register in place. Existing machine must be gone. Not an issue if importing on #a different server. Import-VM -Path $VMConfigPath -Register -whatif #or I could have copied using existing path since original disks still exist in default location $VHDPath = (Join-Path (Join-Path $ExportPath $VMName) "Virtual Hard Disks") #VhdDestinationPath is marked obsolete but it works Import-VM -Path $VMConfigPath -Copy -GenerateNewId -VhdDestinationPath $VHDPath -ComputerName $server #endregion