Export multiple Windows Server 2012 R2 Hyper-V Guests with PowerShell Part II

Expanding upon the basics demonstrated in Part I of this series, let’s now look at exporting multiple machines using a single PowerShell script.  We’ll use the same director structure as outlined in Part I, but here we have a few additional challenges to overcome.

  • Selecting the Virtual Machines to export.
  • Ensuring that we only export one at a time to reduce the disk I/O and resulting disk fragmentation that will occur if simply try to export all of the machines at one time.
  • You want to export the machines while they’re in a running state.

The following PowerShell script will do the job admirably, but let’s take a look at a few key sections that make this possible.

First the assumptions:

  • HyperV Host is running Windows Server 2012 R2 as this will not work on Windows Server 2012.

Then the script:


# $RootPath: Can be changed to point where you’d like the Virtual Machines exported and can be any valid

#            drive path.

$RootPath = ‘E:\Exports-RONBOKEVGA1\Backup\’

# $OutputDate: Is simply used to create a unique folder name that later can have it’s CreationDate checked

#              for deletion later.

$OutputDate = (Get-Date).Year.ToString() + ‘.’ + (Get-Date).Month.ToString() + ‘.’ + (Get-Date).Day.ToString() + ‘.’ + (Get-Date).Hour.ToString() + ‘.’ + (Get-Date).Minute.ToString() + ‘.’ + (Get-Date).Second.ToString()



#Clean up old Export-VM folders older than one month ago to reduce disk space consumption.

foreach ($i in Get-ChildItem $RootPath)


    if ($i.CreationTime -lt ($(Get-Date).AddMonths(-1)))


            #Write-Output $i.Name.ToString()

            Remove-Item $i.PSPath -Recurse




#Create new Export folder with current date/time.

$ExportPath = New-Item ($RootPath + ‘ ‘ + $OutputDate) -type directory


# Set the $Status variable to a default value which should indicate that no VM’s are being exported.

$Status = Get-VM | Where Status -EQ ‘Exporting virtual machine’


Function CheckStatus()




        # We only want to be exporting one VM at a time so that we don’t overtax disk I/O.

        # The function ensures that by checking the VM status before starting the next export.

        Start-Sleep -s 60

        $Status = Get-VM | Where Status -EQ ‘Exporting virtual machine’


        $d = Get-Date -DisplayHint Time


        Write-Host “Exporting…” $d -ForegroundColor Yellow


    } While ($Status.Count -ne 0)




Function ExportVM($VM)


    Export-VM -ComputerName $env:COMPUTERNAME -Name $VM.VMName -Path $ExportPath -AsJob

    Write-Host ‘Starting Export: ‘ $VM.VMName -ForegroundColor Yellow




# This is our list of VM’s to export based on a naming filter.

# It’s important to be consistent when naming VM’s in the Hyper-V Console!

$VMList =  Get-VM | Where-Object {$_.Name -like ‘RonBok*’}

Write-Host $VMList.VMName



ForEach ($VM in $VMList)


    # The DPM VM’s are using physical disks, so they cannot be exported.

    # They’d be so large that it would be impossible anyway.

    If (($VM.VMName -ne ‘RonBokDPM1’) -and ($VM.VMName -ne ‘RonBokDPM2’))


        ExportVM $VM




The key to this whole thing are the two functions ExportVM() and CheckStatus().  CheckStatus() queries the list of VM’s in HyperV and looks for any VM that has a status of ‘Exporting virtual machine’.  It’s rather fragile in that respect, but it works.

The other thing to note is the ForEach loop at the bottom … really the main part of the script.  It creates an object $VMList of all the VM’s in my environment that begin with ‘RonBok*’ as those are the ones I want exported.  For your environment you’ll need to decide what kind of query works best for you and change the script accordingly.  Also note that I have a few System Center Data Protection Manager 2012 R2 machines in this list an want them excluded.  Those VM’s I can’t export anyway because they are using physical disks for storage.  I’ll cover System Center Data Protection Manager 2012 R2 in Part III.

If you have any questions feel free to post in the comments.

Have fun!

Tagged with:
Posted in Hyper-V, PowerShell, Windows Server 2012 R2

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: