Add uninstall-MS-Visual-C++-2010.ps1
This commit is contained in:
parent
e012c2925e
commit
111916ea99
104
uninstall-MS-Visual-C++-2010.ps1
Normal file
104
uninstall-MS-Visual-C++-2010.ps1
Normal file
@ -0,0 +1,104 @@
|
||||
# Remove 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') {
|
||||
# Convert /I {GUID} -> /x {GUID}
|
||||
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 += ' /quiet' }
|
||||
if ($args -notmatch '(?i)/norestart') { $args += ' /norestart' }
|
||||
}
|
||||
Write-Output "Uninstall (MSI) $AppName -> msiexec $args"
|
||||
} else {
|
||||
# Non-MSI: try to enforce silent switches if missing
|
||||
if ($args -notmatch '(?i)/quiet|/qn|/silent|/s') { $args += ' /quiet' }
|
||||
if ($args -notmatch '(?i)/norestart') { $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 {
|
||||
Write-Warning "Error while uninstalling $AppName: $($_.Exception.Message)"
|
||||
$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 |
|
||||
Where-Object {
|
||||
$_.DisplayName -and
|
||||
$_.DisplayName -like 'Microsoft Visual C++ 2010*Redistributable*'
|
||||
}
|
||||
}
|
||||
|
||||
if (-not $targets) {
|
||||
Write-Output 'No Microsoft Visual C++ 2010 Redistributables found. Nothing to do.'
|
||||
exit 0
|
||||
}
|
||||
|
||||
Write-Output ("Found: " + ($targets.DisplayName | Sort-Object -Unique -join ', '))
|
||||
|
||||
# Uninstall each item
|
||||
foreach ($app in $targets) {
|
||||
$name = $app.DisplayName
|
||||
$cmd = if ($app.QuietUninstallString) { $app.QuietUninstallString } else { $app.UninstallString }
|
||||
Invoke-Uninstall -CmdLine $cmd -AppName $name
|
||||
}
|
||||
|
||||
if ($fails -gt 0) {
|
||||
Write-Output "Completed with errors: $fails item(s) failed to uninstall."
|
||||
exit 1
|
||||
} else {
|
||||
Write-Output 'Completed: all target items successfully removed (or not present).'
|
||||
exit 0
|
||||
}
|
Loading…
Reference in New Issue
Block a user