81 lines
2.9 KiB
PowerShell
81 lines
2.9 KiB
PowerShell
# This script is designed for use in Datto RMM (CentraStage).
|
|
# Purpose: Uninstall all "Microsoft Visual C++ 2010 ... Redistributable" (x86/x64), version independent.
|
|
# Exit codes:
|
|
# 0 = OK (nothing found or everything removed successfully)
|
|
# 1 = Failures occurred
|
|
|
|
$ErrorActionPreference = 'Stop'
|
|
$fails = 0
|
|
|
|
function Invoke-Uninstall {
|
|
param(
|
|
[string]$CmdLine,
|
|
[string]$AppName
|
|
)
|
|
|
|
if (-not $CmdLine) {
|
|
Write-Warning ("No UninstallString found for " + $AppName)
|
|
$script:fails++
|
|
return
|
|
}
|
|
|
|
# Normalize to exe + args
|
|
$exe = $null
|
|
$args = ""
|
|
if ($CmdLine -match '^\s*"(.+?)"\s*(.*)$') {
|
|
$exe = $Matches[1]
|
|
$args = $Matches[2]
|
|
} elseif ($CmdLine -match '^\s*(\S+)\s*(.*)$') {
|
|
$exe = $Matches[1]
|
|
$args = $Matches[2]
|
|
}
|
|
|
|
# MSI: force silent uninstall
|
|
if ($exe -match '(?i)msiexec\.exe') {
|
|
if ($args -match '(?i)/I\s*{([0-9A-F\-]+)}') {
|
|
$guid = $Matches[1]
|
|
$args = "/x {" + $guid + "} /quiet /norestart"
|
|
} else {
|
|
if ($args -notmatch '(?i)/x') { $args = "/x " + $args }
|
|
if ($args -notmatch '(?i)/quiet|/qn') { $args = $args + " /quiet" }
|
|
if ($args -notmatch '(?i)/norestart') { $args = $args + " /norestart" }
|
|
}
|
|
Write-Output ("Uninstall (MSI) " + $AppName + " -> msiexec " + $args)
|
|
} else {
|
|
# Non-MSI: try to enforce silent switches
|
|
if ($args -notmatch '(?i)/quiet|/qn|/silent|/s') { $args = $args + " /quiet" }
|
|
if ($args -notmatch '(?i)/norestart') { $args = $args + " /norestart" }
|
|
Write-Output ("Uninstall (EXE) " + $AppName + " -> " + $exe + " " + $args)
|
|
}
|
|
|
|
try {
|
|
$p = Start-Process -FilePath $exe -ArgumentList $args -Wait -PassThru -WindowStyle Hidden
|
|
$code = $p.ExitCode
|
|
# Common msiexec codes: 0=success, 3010=reboot required, 1605=not installed
|
|
if ($exe -match '(?i)msiexec\.exe') {
|
|
if ($code -in 0,3010,1605) {
|
|
if ($code -eq 3010) { Write-Output ("Note: reboot required (3010) for " + $AppName) }
|
|
elseif ($code -eq 1605) { Write-Output ("Not installed (1605) for " + $AppName + ", skipping.") }
|
|
return
|
|
}
|
|
} else {
|
|
if ($code -eq 0) { return }
|
|
}
|
|
Write-Warning ("Uninstall failed for " + $AppName + " with exit code " + $code)
|
|
$script:fails++
|
|
} catch {
|
|
$msg = $_.Exception.Message
|
|
Write-Warning ("Error while uninstalling " + $AppName + ": " + $msg)
|
|
$script:fails++
|
|
}
|
|
}
|
|
|
|
# Pre-check: look for target apps
|
|
$uninstallKeys = @(
|
|
"HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*",
|
|
"HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*"
|
|
)
|
|
|
|
$targets = foreach ($key in $uninstallKeys) {
|
|
Get-ItemProperty -Path $key -ErrorAction SilentlyContinue |
|