Automating VMware Workstation LAB

I am often working with quite large test environments. Powering on ESXi hosts with nested VMs can be a pain when you need to get it running quickly.

Here are some of my tricks to automating VMware Workstation


All my script are based on the VMware PowerCLI powershell modules which can be installed in a modern Powershell using the commands:

Install-Module VMware.PowerCLI
Set-ExecutionPolicy RemoteSigned
Set-PowerCLIConfiguration -InvalidCertificateAction:Ignore -ParticipateInCeip:$false

Now we are good to go, and can load the PowerCLI module using the command:

Import-Modules VMware.PowerCLI

Starting the VMs in VMware Workstation

To get the base VMs started we need to define the VMX path and the expected time for the VM to be ready. This is only necessary for VMs that others depend on. One example could be the VM that provides storage for you ESXi hosts. That needs to be done before you can start the ESXi hosts.

Here are the commands I use to define all my VMs:

$vmx_files = @{}

# $vmx_files.Add(<fill path to vmx file>, <time to boot in seconds>)


Here I have defined that I want the Virtual Router started, and I should just wait for 1 seconds before continuing. Afterwards I start the TrueNAS storage appliance and wait for 60 seconds before starting the hosts. Which I wait for 10 seconds each just to not start everything at once. There is a limit to the storage I/O provided by my local disks.

I then go ahead and define my vCenter address, my host addresses and the VMs that I want started.

$vCenter = "<vCenter>"
$HostsConnections = @('<host1 ip>', 'host2 ip', 'host3 ip')

$RequiredVMs = @{}

# $RequiredVMs.Add(<VM Name>, <time to boot in seconds>)


The order at which I add the VMs are not random. The attributes are similar to the $VMX_FILES hashtable.

Now it’s time to start the VMs.

Write-Host "Starting Workstation VMs"

cd 'C:\Program Files (x86)\VMware\VMware Workstation'
foreach ($vmx in $vmx_files.keys) {
    .\vmrun -T ws start "$($vmx)"
    Start-Sleep -s $vmx_files[$vmx]

Now we try and connect to the ESXi hosts so we can start the nested VMs

Write-Host "Connection to ESXi hosts"
$success = $false
while (-not $success) {
    foreach ($connection in $global:DefaultVIServers) {
        Disconnect-VIServer $connection -Confirm:$false -ErrorAction:Continue

    try {
        foreach ($ip in $HostsConnections)  {
            Connect-VIServer $ip -User root -Password "<password>" -ErrorAction:Stop
        $success = $true

    catch {
        Start-Sleep -s 10
        Write-Host "Retrying ESXi host connections."

Now we can start the nested VMs

foreach ($vmName in $RequiredVMs.keys) {
    $VM = Get-VM | Where-Object { $_.Name -eq $vmName } | Select-Object -First 1
    $VM | Start-VM
    Start-Sleep -s $RequiredVMs[$vmName]

Now we have started vCenter lets drop the Host connections and work directly with vCenter.

foreach ($connection in $global:DefaultVIServers) {
    Disconnect-VIServer $connection -Confirm:$false

$success = $false
while (-not $success) {
    try {
        Connect-VIServer $vCenter -User administrator@vsphere.local -Password "<password>" -ErrorAction:Stop
        $success = $true

    catch {
        Start-Sleep -s 30

Start-Process "https://<vcenter>/ui"

Hope this help someone out. Give me some feedback if there are other things you would like to see automated.

Leave a Reply

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