NEW 🖥️ Infrastructure Automation

Force-Remove Leftover VMware Tools with PowerShell — Registry, File & Service Cleanup

When the normal VMware Tools uninstaller is missing, broken, or simply won't run, this script tears out every registry key, file, and service it left behind — the kind of cleanup you want done properly before moving a VM to Hyper-V or any other hypervisor.

📅 19 June 2026 ✍️ Ravindrakumar Narayanan ⏱️ 8 min read 🏷️ VMware · PowerShell · Windows Server · Migration
📋 In This Article

🚀 Overview

Add/Remove Programs says VMware Tools isn't installed. The MSI uninstaller can't find a product to remove. But C:\Program Files\VMware is still sitting there, a handful of VMware* services are still listed in services.msc, and the registry is full of orphaned Installer\Products entries. This usually happens after a botched upgrade, a Tools package that was removed by deleting files instead of uninstalling properly, or — most commonly — a VM that's being prepared for a move off VMware entirely.

This script does the manual job an engineer would otherwise do by hand: find every trace VMware Tools left in the registry and on disk, show you exactly what it found, and — once you confirm — remove all of it cleanly. It's written for Windows Server 2008 R2 through 2019 and has been tested directly on 2016 and 2019.

⚠️ Don't run this against a healthy install. This is a forced-removal tool for when the normal uninstaller has already failed or is unavailable. If VMware Tools installs/uninstalls normally on your VM, use Programs and Features or the official VMware uninstaller instead.

🔍 Why the Standard Uninstaller Fails

A handful of recurring causes account for most "VMware Tools won't uninstall" situations on generic Windows Server builds:

In every one of these cases, the fix isn't "uninstall again" — there's nothing left for the uninstaller to act on. It's a manual cleanup of the leftovers.

🗂️ What Gets Cleaned Up

The script builds its target list dynamically rather than hardcoding paths, so it adapts to whatever installer IDs are actually present on the box in front of it.

TargetWhy it's there
HKCR\Installer\Products\<ID>
HKCR\Installer\Features\<ID>
The MSI's core product/feature registration — found automatically by matching ProductName = 'VMware Tools'.
HKLM\...\Uninstall\{MSI ProductCode}The entry that drives the Programs and Features list — extracted from the matching product's ProductIcon value.
HKLM\...\Installer\UserData\<every SID>\Products\<ID>Per-user install registration. Walked across every SID under UserData, not just SYSTEM — Tools can be registered under whichever account ran the original install.
HKLM\SOFTWARE\VMware, Inc.Shared configuration hive used by Tools and other VMware components.
C:\Program Files\VMware
C:\Program Files\Common Files\VMware
C:\ProgramData\VMware
Binaries, shared components, and logs/config — ProgramData alone can hold several hundred MB of old log data.
Legacy CLSID / Uninstall GUIDsA small set of fixed entries only added on Windows builds older than Server 2016, where auto-detection is less reliable.
Services matching VMware*, vm*, or named GISvcCovers components whose display name doesn't start with "VMware" — the Guest Info service being the classic example.

✅ Prerequisites & Safety Checklist

1

Run elevated

The script checks for Administrator rights on launch and exits cleanly if it isn't running elevated — registry and Program Files access both require it.

2

Snapshot or back up first

Take a VM snapshot (or a file-level backup if it's already off VMware) before running this on anything you can't easily rebuild.

3

Test on one non-critical server first

Run it interactively on a single, low-priority VM and read the printed target list before rolling it out to anything that matters.

4

PowerShell 5.1 or later

Works on Windows PowerShell 5.1 (built into Server 2016/2019) and PowerShell 7.x. Falls back to sc.exe for service removal if Remove-Service isn't available.

📜 How the Script Works

The flow is linear and deliberately simple to follow — discover, build, filter, confirm, remove:

Find every "VMware Tools" entry under Installer\Products
Build the full target list — registry keys, every UserData SID, legacy GUIDs, folders
Keep only targets that actually exist on this box
Find matching services (VMware*, vm*, GISvc)
Print the full list → confirm (y/n), or skip with -Force
Stop & remove services, then remove registry keys and folders

1. Discovering every orphaned installer entry

Rather than assuming there's exactly one "VMware Tools" registration, the script enumerates Installer\Products and collects every match — important because repeated upgrade/downgrade cycles can leave more than one behind:

PowerShell — installer ID discovery
function Get-VMwareToolsInstallerIDs {
    $found = @()
    Get-ChildItem Registry::HKEY_CLASSES_ROOT\Installer\Products -ErrorAction SilentlyContinue | ForEach-Object {
        if ($_.GetValue('ProductName') -eq 'VMware Tools') {
            $icon  = $_.GetValue('ProductIcon')
            $msiId = $null
            if ($icon) {
                $m = [Regex]::Match($icon, '(?<=\{)(.*?)(?=\})')
                if ($m.Success) { $msiId = $m.Value }
            }
            $found += [PSCustomObject]@{ reg_id = $_.PSChildName; msi_id = $msiId }
        }
    }
    return $found
}

The MSI ProductCode (used to find the matching Uninstall registry key) is pulled out of the ProductIcon value, which embeds it between curly braces.

2. Walking every SID under UserData

This is the part that's easy to get wrong: the per-user MSI registration under UserData isn't always filed under the SYSTEM SID. If Tools was ever installed interactively by an administrator account, the registration sits under that account's SID instead. The script walks all of them:

PowerShell — UserData SID walk
$userDataRoot = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData"
if (Test-Path $userDataRoot) {
    Get-ChildItem $userDataRoot -ErrorAction SilentlyContinue | ForEach-Object {
        $targets += (Join-Path $_.PSPath "Products\$($entry.reg_id)")
    }
}

3. Filtering before the confirmation prompt

Every computed path is checked with Test-Path before it's shown to you, so the list you confirm against matches exactly what will be touched — no theoretical paths that don't actually exist on this particular server.

4. The confirmation gate (or -Force for automation)

PowerShell — confirmation logic
$proceed = $Force.IsPresent
if (-not $proceed) {
    $proceed = (Read-Host "Continue (y/n)") -eq 'y'
}

Run it with no parameters and you get the interactive prompt. Add -Force and it skips straight to removal — what you want when this is driven remotely across several servers rather than typed at a console one at a time.

🖥️ Running It

Interactive — single server

PowerShell — interactive run
# In an elevated PowerShell session on the target server
.\Remove-VMwareTools.ps1

Read the printed list of registry keys, folders, and services carefully, then type y to proceed.

Unattended — for remote or scripted runs

PowerShell — unattended run
.\Remove-VMwareTools.ps1 -Force

Across multiple servers with PowerShell remoting

Once you've validated the behaviour interactively on a test box, the same script can be pushed out to a batch of generic servers via Invoke-Command:

PowerShell — remote batch run
$targetServers = @('SERVER01', 'SERVER02', 'SERVER03')
$cred          = Get-Credential   # local or domain admin on the targets

Invoke-Command -ComputerName $targetServers -Credential $cred -ScriptBlock {
    & 'C:\Scripts\Remove-VMwareTools.ps1' -Force
}
💡 Copy the script to each target first (or drop it on a network share every box can reach) — Invoke-Command -ScriptBlock runs against a local path on the remote machine, it doesn't transfer the file for you.

🚫 What It Doesn't Touch

To keep the script predictable, it deliberately stays out of two areas:

If you want a full hygiene check after migrating off VMware, this is a quick generic sanity check:

CMD — leftover driver check
driverquery /v | findstr /i vmware

💡 Pro Tips & Best Practices

🔑

Snapshot before you run it

Cheap insurance — take it immediately before, not "earlier today".

🧪

Pilot on one box per OS version

2008 R2/2012 R2 hit the legacy GUID block; 2016/2019 don't. Test both paths before a fleet-wide run.

🔁

Reboot before reinstalling

Some services and locked files only fully release after a restart — reboot before attempting a fresh VMware Tools install or hypervisor migration step.

📋

Keep the console output

Redirect the printed target list to a log file per server (... | Tee-Object) if you're running this across a batch — useful evidence if anything needs to be restored.

📦 GitHub Repository

The full script — Remove-VMwaretools.ps1 — is published in the Infra Automation repository, ready to drop onto a Windows agent or run directly on a target server.

View Remove-VMwaretools.ps1 on GitHub
VMware VMware Tools PowerShell Windows Server Registry Cleanup Hyper-V Migration V2V
← Back to Blog More on GitHub →