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

3- Installation of VMtools is just a one click install

4- Click Install.exe to launch the wizard

5- Click Next to proceed

6- Choose Typical

7- Review and click Install to start the installation.

8- Click Finish

10- Reboot the VM for settings to take effect

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
