Uninstall FMA MSIs by UpgradeCode when available (#30581)

Fixes #27757.

# Checklist for submitter

If some of the following don't apply, delete the relevant line.

- [x] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)
- [x] Manual QA for all new/changed functionality

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Improved uninstallation process for MSI-based applications by
dynamically detecting and uninstalling all related product codes using
the upgrade code, enhancing reliability for machine-wide installs.

* **Bug Fixes**
* Updated uninstall scripts for BoxDrive, Cloudflare WARP, and Google
Chrome to ensure complete removal of all associated components.

* **Chores**
* Updated installer versions for Cloudflare WARP and Google Chrome to
the latest releases.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
Ian Littman 2025-07-15 11:38:17 -05:00 committed by GitHub
parent 22ddb12530
commit f4a9eabfd9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 47 additions and 14 deletions

View file

@ -2,6 +2,7 @@ package winget
import (
"context"
_ "embed"
"encoding/json"
"fmt"
"os"
@ -250,6 +251,25 @@ func (i *wingetIngester) ingestOne(ctx context.Context, input inputApp) (*mainta
}
if (input.InstallerType == installerTypeMSI || input.UninstallType == installerTypeMSI) && input.InstallerScope == machineScope {
var upgradeCode string
for _, fe := range m.AppsAndFeaturesEntries {
if fe.UpgradeCode != "" {
upgradeCode = fe.UpgradeCode
break
}
}
if upgradeCode == "" {
for _, fe := range selectedInstaller.AppsAndFeaturesEntries {
if fe.UpgradeCode != "" {
upgradeCode = fe.UpgradeCode
break
}
}
}
if uninstallScript == "" && upgradeCode != "" {
uninstallScript = buildUpgradeCodeBasedUninstallScript(upgradeCode)
}
if uninstallScript == "" {
uninstallScript = file.GetUninstallScript(installerTypeMSI)
}
@ -266,7 +286,6 @@ func (i *wingetIngester) ingestOne(ctx context.Context, input inputApp) (*mainta
if productCode == "" {
productCode = selectedInstaller.ProductCode
}
productCode = strings.Split(productCode, ".")[0]
out.Name = input.Name
@ -303,6 +322,13 @@ func (i *wingetIngester) ingestOne(ctx context.Context, input inputApp) (*mainta
return &out, nil
}
//go:embed uninstall_with_upgrade_code.ps1
var uninstallWithUpgradeCode string
func buildUpgradeCodeBasedUninstallScript(upgradeCode string) string {
return regexp.MustCompile(`\$UPGRADE_CODE`).ReplaceAllString(uninstallWithUpgradeCode, upgradeCode)
}
var packageIDRegex = regexp.MustCompile(`((("\$PACKAGE_ID")|(\$PACKAGE_ID))(?P<suffix>\W|$))|(("\${PACKAGE_ID}")|(\${PACKAGE_ID}))`)
func preProcessUninstallScript(uninstallScript, productCode string) string {

View file

@ -0,0 +1,7 @@
# Fleet uninstalls app by finding all related product codes for the specified upgrade code
$inst = New-Object -ComObject "WindowsInstaller.Installer"
foreach ($product_code in $inst.RelatedProducts('$UPGRADE_CODE')) {
msiexec /quiet /x $product_code
}
Exit $LASTEXITCODE

View file

@ -7,7 +7,7 @@
},
"installer_url": "https://e3.boxcdn.net/desktop/releases/win/BoxDrive-2.45.187.msi",
"install_script_ref": "8959087b",
"uninstall_script_ref": "5999db54",
"uninstall_script_ref": "eeaecda2",
"sha256": "7c3bce4aa53e99fd153542aef4d17beba2a54b4d3d67fdfd260c53cf6f0fbc14",
"default_categories": [
"Productivity"
@ -15,7 +15,7 @@
}
],
"refs": {
"5999db54": "$product_code = \"{EA004022-FC5E-4588-A7EC-EED710BFD9E6}\"\n\n# Fleet uninstalls app using product code that's extracted on upload\nmsiexec /quiet /x $product_code\nExit $LASTEXITCODE\n",
"8959087b": "$logFile = \"${env:TEMP}/fleet-install-software.log\"\n\ntry {\n\n$installProcess = Start-Process msiexec.exe `\n -ArgumentList \"/quiet /norestart /lv ${logFile} /i `\"${env:INSTALLER_PATH}`\"\" `\n -PassThru -Verb RunAs -Wait\n\nGet-Content $logFile -Tail 500\n\nExit $installProcess.ExitCode\n\n} catch {\n Write-Host \"Error: $_\"\n Exit 1\n}\n"
"8959087b": "$logFile = \"${env:TEMP}/fleet-install-software.log\"\n\ntry {\n\n$installProcess = Start-Process msiexec.exe `\n -ArgumentList \"/quiet /norestart /lv ${logFile} /i `\"${env:INSTALLER_PATH}`\"\" `\n -PassThru -Verb RunAs -Wait\n\nGet-Content $logFile -Tail 500\n\nExit $installProcess.ExitCode\n\n} catch {\n Write-Host \"Error: $_\"\n Exit 1\n}\n",
"eeaecda2": "# Fleet uninstalls app by finding all related product codes for the specified upgrade code\n$inst = New-Object -ComObject \"WindowsInstaller.Installer\"\nforeach ($product_code in $inst.RelatedProducts('{46AF5B38-D258-487A-92BD-792911248CCD}')) {\n msiexec /quiet /x $product_code\n}\n\nExit $LASTEXITCODE\n"
}
}

View file

@ -1,21 +1,21 @@
{
"versions": [
{
"version": "25.4.943.0",
"version": "25.5.893.0",
"queries": {
"exists": "SELECT 1 FROM programs WHERE name = 'Cloudflare WARP' AND publisher = 'Cloudflare, Inc.';"
},
"installer_url": "https://downloads.cloudflareclient.com/v1/download/windows/version/2025.4.943.0",
"installer_url": "https://downloads.cloudflareclient.com/v1/download/windows/version/2025.5.893.0",
"install_script_ref": "8959087b",
"uninstall_script_ref": "fad0c0ce",
"sha256": "04108b020b545f778d6bb7ea996a896d5e30f722a1fdf056fe74001228c1fee5",
"uninstall_script_ref": "1d523e72",
"sha256": "ff77a76288adf412e819614795476b9b834b79e5a036aaa554c6e2eabd45c623",
"default_categories": [
"Productivity"
]
}
],
"refs": {
"8959087b": "$logFile = \"${env:TEMP}/fleet-install-software.log\"\n\ntry {\n\n$installProcess = Start-Process msiexec.exe `\n -ArgumentList \"/quiet /norestart /lv ${logFile} /i `\"${env:INSTALLER_PATH}`\"\" `\n -PassThru -Verb RunAs -Wait\n\nGet-Content $logFile -Tail 500\n\nExit $installProcess.ExitCode\n\n} catch {\n Write-Host \"Error: $_\"\n Exit 1\n}\n",
"fad0c0ce": "$product_code = \"{FB9B5C2D-D406-48A5-A9A0-F490DD1ED60C}\"\n\n# Fleet uninstalls app using product code that's extracted on upload\nmsiexec /quiet /x $product_code\nExit $LASTEXITCODE\n"
"1d523e72": "# Fleet uninstalls app by finding all related product codes for the specified upgrade code\n$inst = New-Object -ComObject \"WindowsInstaller.Installer\"\nforeach ($product_code in $inst.RelatedProducts('{1BF42825-7B65-4CA9-AFFF-B7B5E1CE27B4}')) {\n msiexec /quiet /x $product_code\n}\n\nExit $LASTEXITCODE\n",
"8959087b": "$logFile = \"${env:TEMP}/fleet-install-software.log\"\n\ntry {\n\n$installProcess = Start-Process msiexec.exe `\n -ArgumentList \"/quiet /norestart /lv ${logFile} /i `\"${env:INSTALLER_PATH}`\"\" `\n -PassThru -Verb RunAs -Wait\n\nGet-Content $logFile -Tail 500\n\nExit $installProcess.ExitCode\n\n} catch {\n Write-Host \"Error: $_\"\n Exit 1\n}\n"
}
}

View file

@ -1,13 +1,13 @@
{
"versions": [
{
"version": "138.0.7204.50",
"version": "138.0.7204.97",
"queries": {
"exists": "SELECT 1 FROM programs WHERE name = 'Google Chrome' AND publisher = 'Google LLC';"
},
"installer_url": "https://dl.google.com/dl/chrome/install/googlechromestandaloneenterprise64.msi",
"install_script_ref": "8959087b",
"uninstall_script_ref": "ddbf0e7f",
"uninstall_script_ref": "4836150f",
"sha256": "no_check",
"default_categories": [
"Browsers"
@ -15,7 +15,7 @@
}
],
"refs": {
"8959087b": "$logFile = \"${env:TEMP}/fleet-install-software.log\"\n\ntry {\n\n$installProcess = Start-Process msiexec.exe `\n -ArgumentList \"/quiet /norestart /lv ${logFile} /i `\"${env:INSTALLER_PATH}`\"\" `\n -PassThru -Verb RunAs -Wait\n\nGet-Content $logFile -Tail 500\n\nExit $installProcess.ExitCode\n\n} catch {\n Write-Host \"Error: $_\"\n Exit 1\n}\n",
"ddbf0e7f": "$product_code = \"{630C6D4E-5144-3E8C-A7B1-4B3BC607535E}\"\n\n# Fleet uninstalls app using product code that's extracted on upload\nmsiexec /quiet /x $product_code\nExit $LASTEXITCODE\n"
"4836150f": "# Fleet uninstalls app by finding all related product codes for the specified upgrade code\n$inst = New-Object -ComObject \"WindowsInstaller.Installer\"\nforeach ($product_code in $inst.RelatedProducts('{C1DFDF69-5945-32F2-A35E-EE94C99C7CF4}')) {\n msiexec /quiet /x $product_code\n}\n\nExit $LASTEXITCODE\n",
"8959087b": "$logFile = \"${env:TEMP}/fleet-install-software.log\"\n\ntry {\n\n$installProcess = Start-Process msiexec.exe `\n -ArgumentList \"/quiet /norestart /lv ${logFile} /i `\"${env:INSTALLER_PATH}`\"\" `\n -PassThru -Verb RunAs -Wait\n\nGet-Content $logFile -Tail 500\n\nExit $installProcess.ExitCode\n\n} catch {\n Write-Host \"Error: $_\"\n Exit 1\n}\n"
}
}