Skip to content

Instantly share code, notes, and snippets.

@KGHague
Last active July 1, 2025 14:36
Show Gist options
  • Save KGHague/2c562ee88492c1c0c0eac1b3ae0fecd8 to your computer and use it in GitHub Desktop.
Save KGHague/2c562ee88492c1c0c0eac1b3ae0fecd8 to your computer and use it in GitHub Desktop.
function ConvertTo-PackedGuid {
<#
.SYNOPSIS
https://gist.github.com/MyITGuy/d3e039c5ec7865edefc157fcd625a20a
Converts a GUID string into a packed globally unique identifier (GUID) string.
.DESCRIPTION
Takes a GUID string and breaks it into 6 parts. It then loops through the first five parts and reversing the order. It loops through the sixth part and reversing the order of every 2 characters. It then joins the parts back together and returns a packed GUID string.
.EXAMPLE
ConvertTo-PackedGuid -Guid '{7C6F0282-3DCD-4A80-95AC-BB298E821C44}'
The output of this example would be: 2820F6C7DCD308A459CABB92E828C144
.PARAMETER Guid
A globally unique identifier (GUID).
#>
[CmdletBinding()]
[OutputType([System.String])]
param (
[Parameter(ValueFromPipeline, ValueFromPipelineByPropertyName, Mandatory)]
[ValidateScript( { [System.Guid]::Parse($_) -is [System.Guid] })]
[System.Guid]$Guid
)
process {
Write-Verbose "Guid: $($Guid)"
$GuidString = $Guid.ToString('N')
Write-Verbose "GuidString: $($GuidString)"
$Indexes = [ordered]@{
0 = 8
8 = 4
12 = 4
16 = 2
18 = 2
20 = 12
}
$PackedGuid = ''
foreach ($index in $Indexes.GetEnumerator()) {
$Substring = $GuidString.Substring($index.Key, $index.Value)
Write-Verbose "Substring: $($Substring)"
switch ($index.Key) {
20 {
$parts = $Substring -split '(.{2})' | Where-Object { $_ }
foreach ($part In $parts) {
$part = $part -split '(.{1})'
Write-Verbose "Part: $($part)"
[System.Array]::Reverse($part)
Write-Verbose "Reversed: $($part)"
$PackedGuid += $part -join ''
}
}
default {
$part = $Substring.ToCharArray()
Write-Verbose "Part: $($part)"
[System.Array]::Reverse($part)
Write-Verbose "Reversed: $($part)"
$PackedGuid += $part -join ''
}
}
}
[System.Guid]::Parse($PackedGuid).ToString('N').ToUpper()
}
}
# Create an instance of the WindowsInstaller.Installer object
$installer = New-Object -ComObject WindowsInstaller.Installer
# Get the list of installed programs and find the VMware Tools entry
$vmwareTools = Get-WmiObject -Query "SELECT * FROM Win32_Product WHERE Name = 'VMware Tools'"
if ($vmwareTools) {
# Extract the identifying number (GUID)
[guid]$guid = $vmwareTools.IdentifyingNumber
# Convert the guid to a packed guid
[string]$packedguid = ConvertTo-PackedGuid $guid
# Get the LocalPackage path from the registry
$localPackage = Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Products\$packedguid\InstallProperties" | Select-Object -ExpandProperty LocalPackage
if ($localPackage) {
Write-Output "VMware Tools MSI path: $localPackage"
# Open the MSI database in read-write mode
$database = $installer.GetType().InvokeMember("OpenDatabase", "InvokeMethod", $null, $installer, @("$localPackage", 2))
# Remove the VM_LogStart and VM_CheckRequirements rows in the CustomAction table
# VM_CheckRequirements added as recommended by @DanAvni
$query = "DELETE FROM CustomAction WHERE Action='VM_LogStart' OR Action='VM_CheckRequirements'"
$view = $database.GetType().InvokeMember("OpenView", "InvokeMethod", $null, $database, @($query))
$view.GetType().InvokeMember("Execute", "InvokeMethod", $null, $view, $null)
$view.GetType().InvokeMember("Close", "InvokeMethod", $null, $view, $null)
[System.Runtime.InteropServices.Marshal]::FinalReleaseComObject($view)
# Commit the changes and close the database
$database.GetType().InvokeMember("Commit", "InvokeMethod", $null, $database, $null)
[System.Runtime.InteropServices.Marshal]::FinalReleaseComObject($database)
# Uninstall VMware Tools
Start-Process msiexec.exe -ArgumentList "/x `"$localPackage`" /qn" -Wait
} else {
Write-Output "LocalPackage path not found in the registry."
}
} else {
Write-Output "VMware Tools is not installed."
}
@gilbreen
Copy link

gilbreen commented Jul 1, 2025

@DanAvni Thanks!

@KGHague
Copy link
Author

KGHague commented Jul 1, 2025

I've updated the VM_CheckRequirements deletion as suggested by @DanAvni

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment