{"id":9005,"date":"2025-07-02T02:40:30","date_gmt":"2025-07-02T02:40:30","guid":{"rendered":"https:\/\/pariswells.com\/blog\/?p=9005"},"modified":"2025-07-02T02:40:32","modified_gmt":"2025-07-02T02:40:32","slug":"powershell-to-force-remove-vmware-tools","status":"publish","type":"post","link":"https:\/\/pariswells.com\/blog\/research\/powershell-to-force-remove-vmware-tools","title":{"rendered":"Powershell to Force Remove Vmware Tools"},"content":{"rendered":"\n<pre class=\"wp-block-code\"><code class=\"\"># This script will manually rip out all VMware Tools registry entries and files for Windows 2008-2019\n# Tested for 2019, 2016, and probably works on 2012 R2 after the 2016 fixes.\n\n# This function pulls out the common ID used for most of the VMware registry entries along with the ID\n# associated with the MSI for VMware Tools.\nfunction Get-VMwareToolsInstallerID {\n    foreach ($item in $(Get-ChildItem Registry::HKEY_CLASSES_ROOT\\Installer\\Products)) {\n        If ($item.GetValue('ProductName') -eq 'VMware Tools') {\n            return @{\n                reg_id = $item.PSChildName;\n                msi_id = [Regex]::Match($item.GetValue('ProductIcon'), '(?&lt;={)(.*?)(?=})') | Select-Object -ExpandProperty Value\n            }\n        }\n    }\n}\n\n$vmware_tools_ids = Get-VMwareToolsInstallerID\n\n# Targets we can hit with the common registry ID from $vmware_tools_ids.reg_id\n$reg_targets = @(\n    \"Registry::HKEY_CLASSES_ROOT\\Installer\\Features\\\",\n    \"Registry::HKEY_CLASSES_ROOT\\Installer\\Products\\\",\n    \"HKLM:\\SOFTWARE\\Classes\\Installer\\Features\\\",\n    \"HKLM:\\SOFTWARE\\Classes\\Installer\\Products\\\",\n    \"HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Products\\\"\n)\n\n$VMware_Tools_Directory = \"C:\\Program Files\\VMware\"\n$VMware_Common_Directory = \"C:\\Program Files\\Common Files\\VMware\"\n$VMware_Startmenu_Entry = \"C:\\ProgramData\\Microsoft\\Windows\\Start Menu\\Programs\\VMware\\\"\n\n# Create an empty array to hold all the uninstallation targets and compose the entries into the target array\n$targets = @()\n\nIf ($vmware_tools_ids) {\n    foreach ($item in $reg_targets) {\n        $targets += $item + $vmware_tools_ids.reg_id\n    }\n    # Add the MSI installer ID regkey\n    $targets += \"HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{$($vmware_tools_ids.msi_id)}\"\n}\n\n# This is a bit of a shotgun approach, but if we are at a version less than 2016, add the Uninstaller entries we don't\n# try to automatically determine.\nIf ([Environment]::OSVersion.Version.Major -lt 10) {\n    $targets += \"HKCR:\\CLSID\\{D86ADE52-C4D9-4B98-AA0D-9B0C7F1EBBC8}\"\n    $targets += \"HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{9709436B-5A41-4946-8BE7-2AA433CAF108}\"\n    $targets += \"HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{FE2F6A2C-196E-4210-9C04-2B1BC21F07EF}\"\n}\n\n# Add the VMware, Inc regkey\nIf (Test-Path \"HKLM:\\SOFTWARE\\VMware, Inc.\") {\n    $targets += \"HKLM:\\SOFTWARE\\VMware, Inc.\"\n}\n\n# Add the VMware Tools directory\nIf(Test-Path $VMware_Tools_Directory) {\n    $targets += $VMware_Tools_Directory\n}\n\n# Thanks to @Gadgetgeek2000 for pointing out that the script leaves some 500mb of extra artifacts on disk.\n# This blob removes those.\nIf(Test-Path $VMware_Common_Directory) {\n    $targets += $VMware_Common_Directory\n}\n\nIf(Test-Path $VMware_Startmenu_Entry) {\n    $targets += $VMware_Startmenu_Entry\n}\n\n# Create a list of services to stop and remove\n$services = Get-Service -DisplayName \"VMware*\" -ErrorAction SilentlyContinue\n$services += Get-Service -DisplayName \"GISvc\" -ErrorAction SilentlyContinue\n\n# Warn the user about what is about to happen\n# Takes only y for an answer, bails otherwise.\nWrite-Host \"The following registry keys, filesystem folders, and services will be deleted:\"\nIf (!$targets -and !$services ) {\n    Write-Host \"Nothing to do!\"\n}\nelse {\n    $targets\n    $services\n    $user_confirmed = Read-Host \"Continue (y\/n)\"\n    If ($user_confirmed -eq \"y\") {\n\n    # Stop all running VMware Services\n    $services | Stop-Service -Confirm:$false -ErrorAction SilentlyContinue\n\n    # Cover for Remove-Service not existing in PowerShell versions &lt; 6.0\n    If (Get-Command Remove-Service -errorAction SilentlyContinue) {\n        $services | Remove-Service -Confirm:$false -ErrorAction SilentlyContinue\n    }\n    Else {\n        foreach ($s in $services) {\n            sc.exe DELETE $($s.Name)\n        }\n    }\n    $dep = Get-Service -Name \"EventLog\" -DependentServices | Select-Object -Property Name\n    Stop-Service -Name \"EventLog\" -Force\n    Stop-Service -Name \"wmiApSrv\" -Force\n    $dep += Get-Service -Name \"winmgmt\" -DependentServices | Select-Object -Property Name\n    Stop-Service -Name \"winmgmt\" -Force\n    Start-Sleep -Seconds 5\n\n    # Remove all the files that are listed in $targets\n    foreach ($item in $targets) {\n        If(Test-Path $item) {\n            Get-Childitem -Path $item -Recurse | Remove-Item -Force -Recurse -ErrorAction SilentlyContinue\n            Remove-Item -Path $item -Recurse -Force\n        }\n    }\n    Start-Service -Name \"EventLog\"\n    Start-Service -Name \"wmiApSrv\"\n    Start-Service -Name \"winmgmt\"\n    foreach ($service in $dep) {\n        Start-Service $service.Name -ErrorAction SilentlyContinue\n    }\n    Write-Host \"Done. Reboot to complete removal.\"\n    }\n    Else {\n        Write-Host \"Failed to get user confirmation\"\n    }\n}<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-9005","post","type-post","status-publish","format-standard","hentry","category-research"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/pariswells.com\/blog\/wp-json\/wp\/v2\/posts\/9005","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/pariswells.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/pariswells.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/pariswells.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/pariswells.com\/blog\/wp-json\/wp\/v2\/comments?post=9005"}],"version-history":[{"count":1,"href":"https:\/\/pariswells.com\/blog\/wp-json\/wp\/v2\/posts\/9005\/revisions"}],"predecessor-version":[{"id":9006,"href":"https:\/\/pariswells.com\/blog\/wp-json\/wp\/v2\/posts\/9005\/revisions\/9006"}],"wp:attachment":[{"href":"https:\/\/pariswells.com\/blog\/wp-json\/wp\/v2\/media?parent=9005"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/pariswells.com\/blog\/wp-json\/wp\/v2\/categories?post=9005"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/pariswells.com\/blog\/wp-json\/wp\/v2\/tags?post=9005"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}