Updating Windows installers (#31076)

- Changed to URLs that will always pull the latest versions of software and using their `msi` instead of `exe`
This commit is contained in:
Allen Houchins
2025-07-20 00:30:12 -05:00
committed by GitHub
parent 4d08af4649
commit 5e8da8a596
4 changed files with 233 additions and 143 deletions
@@ -1,145 +1,247 @@
# Fleet extracts name from installer (EXE) and saves it to PACKAGE_ID
# variable
# Slack Uninstall Script
# This script handles both MSI and EXE installations, including per-user installations
$softwareName = "Slack"
# It is recommended to use exact software name here if possible to avoid
# uninstalling unintended software.
$softwareNameLike = "*$softwareName*"
# Define an array of common silent uninstall parameters to try
$silentParams = @("/S", "/s", "/silent", "/quiet", "-s", "--silent", "/SILENT", "/VERYSILENT", "/NORESTART", "-q", "--quiet")
$machineKey = `
'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*'
$machineKey32on64 = `
'HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*'
$exitCode = 0
$uninstalled = $false
try {
[array]$uninstallKeys = Get-ChildItem `
-Path @($machineKey, $machineKey32on64) `
-ErrorAction SilentlyContinue |
ForEach-Object { Get-ItemProperty $_.PSPath }
Write-Host "Starting Slack uninstallation process..."
$foundUninstaller = $false
foreach ($key in $uninstallKeys) {
# If needed, add -notlike to the comparison to exclude certain similar
# software
if ($key.DisplayName -like $softwareNameLike) {
$foundUninstaller = $true
Write-Host "Found software: $($key.DisplayName)"
# Function to uninstall MSI packages
function Remove-SlackMSI {
Write-Host "Checking for MSI-based Slack installations..."
# Find all Slack MSI products
$msiProducts = Get-WmiObject -Class Win32_Product -Filter "Name LIKE '%Slack%'" -ErrorAction SilentlyContinue
if ($msiProducts) {
foreach ($product in $msiProducts) {
Write-Host "Found MSI: $($product.Name) - Version: $($product.Version)"
Write-Host "Attempting to uninstall MSI..."
# Get the uninstall string without any arguments
$baseUninstallCommand = $key.UninstallString
# The uninstall command may contain command and args, like:
# "C:\Program Files\Software\uninstall.exe" --uninstall --silent
# Extract just the executable path
$splitArgs = $baseUninstallCommand.Split('"')
if ($splitArgs.Length -gt 1) {
$baseUninstallCommand = $splitArgs[1]
# Get any existing arguments
$existingArgs = ""
if ($splitArgs.Length -ge 3) {
$existingArgs = $splitArgs[2].Trim()
try {
$result = $product.Uninstall()
if ($result.ReturnValue -eq 0) {
Write-Host "Successfully uninstalled MSI: $($product.Name)"
return $true
} else {
Write-Host "MSI uninstall returned code: $($result.ReturnValue)"
}
} catch {
Write-Host "Error uninstalling MSI: $_"
}
Write-Host "Base uninstall command: $baseUninstallCommand"
$uninstallSuccess = $false
# First, try QuietUninstallString if it exists
if ($key.QuietUninstallString) {
Write-Host "Trying QuietUninstallString: $($key.QuietUninstallString)"
$processOptions = @{
FilePath = $baseUninstallCommand
PassThru = $true
Wait = $true
}
# Extract arguments from QuietUninstallString if they exist
$quietSplitArgs = $key.QuietUninstallString.Split('"')
if ($quietSplitArgs.Length -ge 3) {
$quietArgs = $quietSplitArgs[2].Trim()
if ($quietArgs) {
$processOptions.ArgumentList = "$quietArgs"
}
}
# Start process and track exit code
$process = Start-Process @processOptions
$exitCode = $process.ExitCode
Write-Host "QuietUninstallString exit code: $exitCode"
if ($exitCode -eq 0) {
Write-Host "Uninstallation successful with QuietUninstallString"
$uninstallSuccess = $true
}
}
# If QuietUninstallString didn't work or doesn't exist, try each silent parameter
if (-not $uninstallSuccess) {
foreach ($param in $silentParams) {
Write-Host "Attempting uninstallation with parameter: $param"
# Combine existing args with silent parameter
$combinedArgs = if ($existingArgs) {
"$existingArgs $param"
} else {
"$param"
}
$processOptions = @{
FilePath = "$baseUninstallCommand"
ArgumentList = "$combinedArgs"
PassThru = $true
Wait = $true
}
# Start process and track exit code
$process = Start-Process @processOptions
$exitCode = $process.ExitCode
Write-Host "Uninstall exit code: $exitCode"
# Check if uninstallation was successful (typically exit code 0)
if ($exitCode -eq 0) {
Write-Host "Uninstallation successful with parameter: $param"
$uninstallSuccess = $true
break # Exit the loop if uninstallation was successful
}
Write-Host "Uninstallation with parameter $param failed. Trying next parameter..."
# Add a short delay between attempts
Start-Sleep -Seconds 2
}
}
if (-not $uninstallSuccess) {
Write-Host "All uninstallation attempts failed."
$exitCode = 1
}
# Exit the loop once the software is found and uninstallation is attempted
break
}
}
# Also try using msiexec with product codes from registry
$msiKeys = @(
'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*',
'HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*',
'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*'
)
foreach ($keyPath in $msiKeys) {
$keys = Get-ChildItem -Path $keyPath -ErrorAction SilentlyContinue |
ForEach-Object { Get-ItemProperty $_.PSPath -ErrorAction SilentlyContinue }
foreach ($key in $keys) {
if ($key.DisplayName -like "*Slack*" -and $key.PSChildName -match '^{[A-F0-9]{8}-[A-F0-9]{4}-[A-F0-9]{4}-[A-F0-9]{4}-[A-F0-9]{12}}$') {
Write-Host "Found MSI product code: $($key.PSChildName)"
Write-Host "Attempting msiexec uninstall..."
$msiArgs = @("/x", $key.PSChildName, "/qn", "/norestart", "REBOOT=ReallySuppress")
$process = Start-Process -FilePath "msiexec.exe" -ArgumentList $msiArgs -Wait -PassThru -NoNewWindow
if ($process.ExitCode -eq 0) {
Write-Host "Successfully uninstalled via msiexec"
return $true
} else {
Write-Host "msiexec returned exit code: $($process.ExitCode)"
}
}
}
}
return $false
}
if (-not $foundUninstaller) {
Write-Host "Uninstaller for '$softwareName' not found."
# Change exit code to 0 if you don't want to fail if uninstaller is not
# found. This could happen if program was already uninstalled.
# Function to uninstall EXE-based installations
function Remove-SlackEXE {
Write-Host "Checking for EXE-based Slack installations..."
$uninstallKeys = @(
'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*',
'HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*',
'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*'
)
$foundAny = $false
foreach ($keyPath in $uninstallKeys) {
$keys = Get-ChildItem -Path $keyPath -ErrorAction SilentlyContinue |
ForEach-Object { Get-ItemProperty $_.PSPath -ErrorAction SilentlyContinue }
foreach ($key in $keys) {
if ($key.DisplayName -like "*Slack*") {
$foundAny = $true
Write-Host "Found: $($key.DisplayName) at $($keyPath)"
if ($key.UninstallString) {
# Extract the executable path and arguments
$uninstallString = $key.UninstallString
$exePath = ""
$arguments = ""
if ($uninstallString -match '^"([^"]+)"(.*)') {
$exePath = $matches[1]
$arguments = $matches[2].Trim()
} elseif ($uninstallString -match '^([^\s]+)(.*)') {
$exePath = $matches[1]
$arguments = $matches[2].Trim()
}
Write-Host "Uninstall executable: $exePath"
# For Slack, common silent parameters
$silentParams = @(
"--uninstall --force-uninstall",
"--uninstall",
"/S",
"/SILENT",
"-s"
)
# First try QuietUninstallString if available
if ($key.QuietUninstallString) {
Write-Host "Trying QuietUninstallString..."
$process = Start-Process -FilePath "cmd.exe" -ArgumentList "/c `"$($key.QuietUninstallString)`"" -Wait -PassThru -NoNewWindow
if ($process.ExitCode -eq 0) {
Write-Host "Successfully uninstalled using QuietUninstallString"
return $true
}
}
# Try each silent parameter
foreach ($param in $silentParams) {
Write-Host "Trying with parameters: $param"
try {
$fullArgs = if ($arguments) { "$arguments $param" } else { $param }
$process = Start-Process -FilePath $exePath -ArgumentList $fullArgs -Wait -PassThru -NoNewWindow -ErrorAction Stop
if ($process.ExitCode -eq 0) {
Write-Host "Successfully uninstalled with parameters: $param"
return $true
} else {
Write-Host "Exit code: $($process.ExitCode)"
}
} catch {
Write-Host "Error: $_"
}
}
}
}
}
}
if (-not $foundAny) {
Write-Host "No EXE-based Slack installations found in registry"
}
return $false
}
# Function to kill Slack processes
function Stop-SlackProcesses {
Write-Host "Checking for running Slack processes..."
$processes = Get-Process -Name "Slack*" -ErrorAction SilentlyContinue
if ($processes) {
Write-Host "Found $($processes.Count) Slack process(es). Attempting to stop..."
foreach ($proc in $processes) {
try {
$proc | Stop-Process -Force -ErrorAction Stop
Write-Host "Stopped process: $($proc.ProcessName) (PID: $($proc.Id))"
} catch {
Write-Host "Failed to stop process: $($proc.ProcessName) - $_"
}
}
Start-Sleep -Seconds 2
}
}
# Function to clean up Slack folders
function Remove-SlackFolders {
Write-Host "Cleaning up Slack folders..."
$foldersToRemove = @(
"$env:LOCALAPPDATA\Slack",
"$env:APPDATA\Slack",
"$env:ProgramFiles\Slack",
"${env:ProgramFiles(x86)}\Slack"
)
foreach ($folder in $foldersToRemove) {
if (Test-Path $folder) {
Write-Host "Removing folder: $folder"
try {
Remove-Item -Path $folder -Recurse -Force -ErrorAction Stop
Write-Host "Successfully removed: $folder"
} catch {
Write-Host "Failed to remove folder: $_"
}
}
}
}
# Main uninstallation logic
try {
# Stop Slack processes first
Stop-SlackProcesses
# Try MSI uninstallation first
$msiResult = Remove-SlackMSI
if ($msiResult) {
$uninstalled = $true
Write-Host "Slack uninstalled via MSI method"
}
# Try EXE uninstallation
$exeResult = Remove-SlackEXE
if ($exeResult) {
$uninstalled = $true
Write-Host "Slack uninstalled via EXE method"
}
# Clean up folders regardless of uninstall method success
Remove-SlackFolders
# Final verification
Start-Sleep -Seconds 3
$remainingInstalls = @(
Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*" -ErrorAction SilentlyContinue |
Where-Object { $_.DisplayName -like "*Slack*" }
Get-ItemProperty "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*" -ErrorAction SilentlyContinue |
Where-Object { $_.DisplayName -like "*Slack*" }
Get-ItemProperty "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*" -ErrorAction SilentlyContinue |
Where-Object { $_.DisplayName -like "*Slack*" }
)
if ($remainingInstalls.Count -eq 0) {
Write-Host "Verification: No Slack installations found in registry"
$exitCode = 0
} elseif ($uninstalled) {
Write-Host "Warning: Some Slack registry entries remain, but uninstallation was attempted"
$exitCode = 0
} else {
Write-Host "Error: Slack uninstallation failed"
$exitCode = 1
}
} catch {
Write-Host "Error: $_"
Write-Host "Critical error during uninstallation: $_"
$exitCode = 1
}
Write-Host "Slack uninstallation script completed with exit code: $exitCode"
Exit $exitCode
@@ -1,11 +1,7 @@
url: https://downloads.slack-edge.com/desktop-releases/windows/x64/4.44.60/SlackSetup.exe
url: http://slack.com/ssb/download-win64-msi
self_service: true
categories:
- Productivity
- Communication
labels_include_any:
- "x86-based Windows hosts"
install_script:
path: ../scripts/default-exe-install-script.ps1
uninstall_script:
path: ../scripts/uninstall-slack.ps1
@@ -1,10 +1,6 @@
url: https://zoom.us/client/latest/ZoomInstaller.exe?archType=winarm64
url: https://zoom.us/client/latest/ZoomInstallerFull.msi?archType=winarm64
self_service: true
categories:
- Communication
labels_include_any:
- "ARM-based Windows hosts"
install_script:
path: ../scripts/default-exe-install-script.ps1
uninstall_script:
path: ../scripts/uninstall-zoom.ps1
@@ -1,10 +1,6 @@
url: https://zoom.us/client/latest/ZoomInstaller.exe?archType=x64
url: https://zoom.us/client/latest/ZoomInstallerFull.msi?archType=x64
self_service: true
categories:
- Communication
labels_include_any:
- "x86-based Windows hosts"
install_script:
path: ../scripts/default-exe-install-script.ps1
uninstall_script:
path: ../scripts/uninstall-zoom.ps1