PowerCLI Basic Scripts: Bulk Export All Virtual Machines in a Folder

Have you ever wanted to mass export virtual machines? I know I have and its infuriating that the web GUI does not have this option built into it. So I went and pulled some good ol’ duct tape engineering and made a somewhat functional script for it.

 

Firstly, we need to connect to the VMware vCenter server. This commandlet allows you to pass credentials in the command/script, or by using the PowerShell equivalent of readline. So if you’re okay with being insecure and bad habits, remove the # and fill in your credentials.

Connect-VIServer -Server YourVcenter.full.tld #-User administrator@vsphere.local -Password Password123!

If you have an invalid SSL certificate, make sure to add this before the line above to ignore the issue and continue anyways:

Set-PowerCLIConfiguration -InvalidCertificateAction Ignore -Confirm:$false

 

Now we need to figure out the folder structure, creating a Get-Folder "FolderName" for each time we enter a folder. For mine I enter 2 folders where VM’s are contained.

For me, this would be 2 total get folder commands. So it would be:

Get-Folder "CCDC" | Get-Folder "Athens"

We then need to get the output from that last folder and sort the output, selecting only the name.

| Get-VM | Select -ExpandProperty Name

Next, we need to format the list as a string to sort out the weirdness

| Out-String | Format-list

Next, we need to set a location of the output text file that contains all of the virtual machines we are going to export. I am using “C:\Temp\dump.txt”.

I tried to use a variable, but PowerCLI had a stroke when calling that variable, so I am using an output file. If you have a method that does not need a dump file, please post it in the comments.

| Out-File C:\Temp\dump.txt

The complete one-liner would be:

Get-Folder "CCDC" | Get-Folder "Athens"| Get-VM | Select -ExpandProperty Name | Out-String | Format-list | Out-File C:\Temp\dump.txt

 

Now we need to load that dump file we created into a variable. Make sure to replace it with your dump file

$vm_names = Get-Content C:\Temp\dump.txt

 

Next is the fun part. Actually exporting the VM’s, or VApps as VMware calls it. From here there are some options you can add. The Export-VApp line is the actual command that exports the VM. You will need to set an output directory for this to work. In my case, it’s a network drive S:\Athens. If you want to export all of the virtual machines at the same time, add “-RunAsync:$true” I caution against using it because it will not increase export times, as it seems there is a hard cap of about 10-20MB/s when exporting VM’s and it is much harder to keep track of the completion process. I also disabled the creation of a separate folder for each VM. I also specified the format be OVF, which is the one that the VM is split into multiple files. If you want a single file the specify OVA.

foreach ($vm_name in $vm_names)
{
Get-VM -Name $vm_name | Shutdown-VMGuest -confirm:$false # This will shutdown the VM before export. 
Get-VM -Name $vm_name | Get-CDDrive | Set-CDDrive -NoMedia -confirm:$false # This will remove any CD in the drive. 
Get-VM -Name $vm_name | Export-VApp -Destination 'S:\Athens' -Format OVF -CreateSeparateFolder:$false
}

This script is pretty modular, so you could for example switch out the commands to instead of exporting a VM, change a network adapter to # port group, Bulk shutdown/startup machines, Mass delete VM’s, etc. If you found this helpful, please consider donating to us. Our server hosting is about 15 bucks a month, So every bit helps.

Complete script:

Set-PowerCLIConfiguration -InvalidCertificateAction Ignore -Confirm:$false
Connect-VIServer -Server vcenter.lok.tech #-User administrator@vsphere.local #-Password

Get-Folder "Folder1" | Get-Folder "FolderInsideFolder1" | Get-VM | Select -ExpandProperty Name | Out-String | Format-list | Out-File C:\Temp\dump.txt

$vm_names = Get-Content C:\Temp\dump.txt

foreach ($vm_name in $vm_names)
{
Get-VM -Name $vm_name | Shutdown-VMGuest -confirm:$false
Get-VM -Name $vm_name | Get-CDDrive | Set-CDDrive -NoMedia -confirm:$false
Get-VM -Name $vm_name | Export-VApp -Destination 'S:\Athens' -Format OVF -CreateSeparateFolder:$false
}

About: Ryan Parker

I'm a former captain of the Cyber Defense team, Current Infrastructure Security Specialist. I also have a side job helping small to medium business with anything technology doing everything imaginable. One of my hobbies is building out infrastructures for myself, friends, and clients. I current maintain a homelab with about 2TB of RAM, 180+ TB of storage, tons of CPU cores, and 100gbit networking backbone.


Leave a Reply

Your email address will not be published. Required fields are marked *