How to Install VMware Tools on Virtual Machine

In this blog, we will learn to install VM tools on our Windows VM via GUI & Powershell.

Install VMware Tools via GUI

1- On a powered Windows VM, Go to Guest OS > Install VM Tools.

2- Select the Mount button to mount the disk image on the OS

install vmware tools mount

3- Installation of VMtools is just a one click install

this pc

4- Click Install.exe to launch the wizard

install vmware tools preparing

5- Click Next to proceed

vmware tools setup

6- Choose Typical

vmware tools setup typical

7- Review and click Install to start the installation.

ready to install vmware tools

8- Click Finish

vmware tools setup completed

10- Reboot the VM for settings to take effect

vmware tools setup restart

Upgrade VMware Tools Automatically

The below writeup is a quick workaround to install VMtools automatically on a Windows VM when the VM gets rebooted.

1- Edit Settings > VM Options > Enable the option to update tools automatically

Copy all the VM names to vmlist.txt and run the script

# 1. Connect
Connect-VIServer "vcenter01.ash.local" -User "VSPHERE.LOCAL\Administrator"

$VMList = Get-Content "C:\Scripts\vmlist.txt"
$LogFile = "C:\Scripts\Tools_Upgrade_Results.txt"

foreach ($VMName in $VMList) {
    $VM = Get-VM -Name $VMName -ErrorAction SilentlyContinue

    if (-not $VM) {
        "ERROR: $VMName not found" | Out-File $LogFile -Append
        continue
    }

    Write-Host "`nTarget: $($VM.Name)" -ForegroundColor Cyan
    Read-Host "Press ENTER to set Upgrade Policy (or Ctrl+C to stop)"

    try {
        # This is the "Universal" way that works on all PowerCLI versions
        $spec = New-Object VMware.Vim.VirtualMachineConfigSpec
        $spec.Tools = New-Object VMware.Vim.ToolsConfigInfo
        $spec.Tools.ToolsUpgradePolicy = "upgradeAtPowerCycle"

        # Apply the change
        $VM.ExtensionData.ReconfigVM($spec)
        
        $Msg = "$($VM.Name) - SUCCESS"
        Write-Host $Msg -ForegroundColor Green
        $Msg | Out-File $LogFile -Append
    } catch {
        $Msg = "$($VM.Name) - FAILED: $($_.Exception.Message)"
        Write-Host $Msg -ForegroundColor Red
        $Msg | Out-File $LogFile -Append
    }
}

Disconnect-VIServer * -Confirm:$false

If you wanted to just apply on Windows VM’s

# 1. Connect
Connect-VIServer "vcenter01.ash.local" 

$VMNames = Get-Content "C:\Scripts\vmlist.txt"
$LogFile = "C:\Scripts\Tools_Upgrade_Results.txt"

Write-Host "Gathering VM data..." -ForegroundColor Yellow
$TargetVMs = Get-VM | Where-Object { $VMNames -contains $_.Name }

foreach ($VM in $TargetVMs) {
    
    # --- FILTERS (With Visibility) ---
    $SkipReason = $null
    if ($VM.ExtensionData.Config.Template) { $SkipReason = "Template" }
    elseif ($VM.PowerState -ne "PoweredOn") { $SkipReason = "Powered $($VM.PowerState)" }
    elseif ($VM.Guest.GuestFamily -ne "windowsGuest") { $SkipReason = "Not Windows ($($VM.Guest.GuestFamily))" }

    if ($SkipReason) {
        Write-Host "Skipping: $($VM.Name) [$SkipReason]" -ForegroundColor Gray
        continue
    }

    # --- SHOW CHANGE CONTROL ---
    $CurrentPolicy = $VM.ExtensionData.Config.Tools.ToolsUpgradePolicy
    if ($CurrentPolicy -eq $null) { $CurrentPolicy = "manual" } # API default is often null/manual

    # If already set, we show it and move on
    if ($CurrentPolicy -eq "upgradeAtPowerCycle") {
        Write-Host "Compliant: $($VM.Name) (Already set to upgradeAtPowerCycle)" -ForegroundColor DarkGreen
        continue
    }

    # --- INTERACTIVE PROMPT ---
    Write-Host "`n==========================================" -ForegroundColor White
    Write-Host "Target VM: $($VM.Name)" -ForegroundColor Cyan
    Write-Host "Current Policy: " -NoNewline; Write-Host $CurrentPolicy -ForegroundColor Red
    Write-Host "New Policy:     " -NoNewline; Write-Host "upgradeAtPowerCycle" -ForegroundColor Green
    
    $Confirm = Read-Host "Apply this change? (Press ENTER to Confirm, 'S' to Skip, Ctrl+C to Stop)"

    if ($Confirm -eq 's') {
        Write-Host "Skipped by user." -ForegroundColor Yellow
        continue
    }

    # --- EXECUTION ---
    try {
        $spec = New-Object VMware.Vim.VirtualMachineConfigSpec
        $spec.Tools = New-Object VMware.Vim.ToolsConfigInfo
        $spec.Tools.ToolsUpgradePolicy = "upgradeAtPowerCycle"

        $VM.ExtensionData.ReconfigVM($spec)
        
        Write-Host "VERIFYING..." -NoNewline
        # Refresh the object to confirm
        $Verify = Get-VM $VM.Name
        if ($Verify.ExtensionData.Config.Tools.ToolsUpgradePolicy -eq "upgradeAtPowerCycle") {
            Write-Host " [OK] Change Applied successfully." -ForegroundColor Green
            "$($VM.Name) - SUCCESS: Updated from $CurrentPolicy" | Add-Content $LogFile
        }
    } catch {
        Write-Host " [ERROR] $($_.Exception.Message)" -ForegroundColor Red
        "$($VM.Name) - FAILED: $($_.Exception.Message)" | Add-Content $LogFile
    }
}

Disconnect-VIServer * -Confirm:$false
(Visited 358 times, 1 visits today)

By C A Thomas

Chinchu A. Thomas is an Infrastructure Analyst specializing in Microsoft Azure, the Microsoft 365 suite, AWS, and Windows infrastructure management products.

Leave a Reply