Clone VM on Win 2012 Hyper-V v3 when it is running using Powershell

I wanted to create a function that could help an IT Pro Admin with the task to create a clone of a running VM, Yes you can use the Export-VM cmdlet but then your VM must be turned off and in some cases, for example when you want to test a new release or patch on a production system but first test it in a safe environment and you are not allowed to stop the original VM.

The function exists in System Center Virtual Machine Manager but there it also must be turned off

So how do I do? I have made a PowerShell function that take a snapshot, copies the vhd files and creates a new VM, connect the vhd´s and network cards, configures the VM with number of processors, dynamic memory etc.

As the Snapshot merges the vhdx files when the VM is running in this new Hyper-V version I thought it was an sufficient way to solve that the VM actually was not writing to the .vhdx files when I copy them but into the .avhdx diff file.

This is a version 0.1 and yes it need some development but right now I do not have the time to make it supernice,

Here you can see it in action

And when It is finished It looks like this in the gui

And here is the PowerShell function

   Function to clone a running VM
   This function can be used to clone a running vm and connect the copied vhd´s and network
   Clone-VM -VMName vmdisktest -VMCloneName vmdisktest-clone -Path c:\VMs
   Clone-VM -VMName vmdisktest -VMCloneName vmdisktest-clone -Path c:\VMs -Switch Private
Author: Niklas Akerlund
Date: 2012-06-19
function Clone-VM
        # Name of the VM to be cloned
        [string] $VMCloneName,
        # Where to store the VM-clone 
        [string] $Path,
        # Set to another network switch
        [string] $Switch = " "    

    # Get VM
    $VM = Get-VM $VMName
    $VHDs = Get-VMHardDiskDrive -VM $VM
    #$VHDPath = (Get-VMHardDiskDrive -VM $VM).Path
    $VHDClonePath = "$Path\$VMCloneName\Virtual Hard Disks\"
    # Create a new array of VHD info
    $VHDOrg = @()
    foreach ($VHD in $VHDs){
        $data = New-Object PSObject -property @{
            VHDName = (Get-Item $VHD.Path).Name
            VHDPath = $VHD.Path
            ControllerType = $VHD.ControllerType
            ControllerNumber = $VHD.ControllerNumber
            ControllerLocation = $VHD.ControllerLocation

        $VHDOrg +=$data

    $VMNics = Get-VMNetworkAdapter -VM $VM

    # Take snapshot 
    $VM | Checkpoint-VM 

    New-Item -ItemType directory -Path $VHDClonePath

    New-VM -Name $VMCloneName -Path $Path -NoVHD -MemoryStartupBytes $VM.MemoryStartup -BootDevice IDE
    $VMClone = Get-VM -Name $VMCloneName
    Get-VMNetworkAdapter -VMName $VMCloneName | Remove-VMNetworkAdapter
    # Configure VM-Clon
    if ($VM.DynamicMemoryEnabled){
        Set-VM -VMName $VMCloneName -ProcessorCount $VM.ProcessorCount -DynamicMemory -MemoryMinimumBytes $VM.MemoryMinimum -MemoryMaximumBytes $VM.MemoryMaximum
        Set-VM -VMName $VMCloneName -ProcessorCount $VM.ProcessorCount -StaticMemory

    # Add all network cards
    foreach ($VMNic in $VMNics){
        if ($Switch -eq " "){
            Add-VMNetworkAdapter -VMName $VMCloneName -SwitchName $VMNic.SwitchName -IsLegacy $VMNic.IsLegacy
            Add-VMNetworkAdapter -VMName $VMCloneName -SwitchName $Switch -IsLegacy $VMNic.IsLegacy

    # Copy all VHDs
    foreach ($VHDcopy in $VHDOrg){
        $Dest = $VHDClonePath + $VHDcopy.VHDName
        Copy-Item -Path $VHDcopy.VHDPath -Destination $Dest
        Add-VMHardDiskDrive -VMName $VMCloneName -ControllerType $VHDCopy.ControllerType -ControllerLocation $VHDCopy.ControllerLocation  -ControllerNumber $VHDCopy.ControllerNumber -Path $Dest   

    # Remove snapshot 
    $VM | Remove-VMSnapshot


Good luck in testing, but do take in consideration that this is an copy of the running VM so do not start it at the same time on the same network or you will get IP collision etc, as you can see above I have added an -Switch parameter that you can use to set the network cards of the VM to be connected on another switch to avoid any problems.. 🙂


Christian Saborío

Great stuff, thanks for sharing! We’ll try and test the script when we get a chance and will post back any bugs or improvements we find, cheers!

Sebastian Haensch

you article doesn’t mention sysprep – don’t you sysprep your machines before cloning?


When I do a clone it is the exact copy of a running machine so no sysprep as you want it to be the same 🙂


Great job, thank you very much!


Hello Niklas,
very cool script , but if I clone a GEN2 VM the script creates a GEN1 VM 🙂 . Thanks for your support, regards Steffen

Thom Schumacher

Nice script

Thom Schumacher


After using your function with hyper-v on my desktop with version 5.0 powershell. Discovered the following requires lines fixed issues I had when using your script again.

#requires -version 3.0
#requires -module hyper-v

the Hyper-v module being the most important.

Leave a comment


email* (not published)