PowerShell – Script to uninstall Adobe Acrobat Reader

Script to stop process, verify installation version, uninstall, log for 32/64bit version.
<#
.SYNOPSIS
Detects and silently uninstalls Adobe Acrobat Reader (32-bit or 64-bit), stops processes/services, verifies removal, and logs to C:\logs\<date>\uninstall.log
.NOTES
- Designed for PowerShell 5.1 on Windows.
- Run as Administrator.
- Use at your own risk; test in a safe environment before wide deployment.
#>
# -------------------------
# Elevation check
# -------------------------
if (-not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
Write-Host "This script must be run as Administrator." -ForegroundColor Red
exit 1
}
# -------------------------
# Logging helpers
# -------------------------
function Get-LogPath {
$date = (Get-Date).ToString('yyyy-MM-dd')
$dir = Join-Path -Path 'C:\logs' -ChildPath $date
if (-not (Test-Path $dir)) { New-Item -Path $dir -ItemType Directory -Force | Out-Null }
return Join-Path -Path $dir -ChildPath 'uninstall.log'
}
$LogFile = Get-LogPath
function Log {
param([string]$Message, [string]$Level = "INFO")
$ts = (Get-Date).ToString('yyyy-MM-dd HH:mm:ss')
$line = "$ts [$Level] $Message"
$line | Out-File -FilePath $LogFile -Encoding UTF8 -Append
Write-Host $line
}
# -------------------------
# Utility: normalize uninstall string to executable + args
# -------------------------
function Parse-UninstallString {
param([string]$UninstallString)
# Trim quotes and whitespace
$s = $UninstallString.Trim()
# If starts with "MsiExec.exe" or "msiexec", return msiexec and args
if ($s -match '(?i)msiexec') {
# ensure /qn for silent uninstall
# If uninstall string contains /I or /X with a product code, keep product code and use /qn
# Example: MsiExec.exe /I{GUID} or MsiExec.exe /X{GUID}
$exe = "msiexec.exe"
# Replace /I with /X to uninstall if necessary
$args = $s -replace '(?i)msiexec.exe','' -replace '(?i)/I','/X'
if ($args -notmatch '(?i)/qn') { $args += " /qn /norestart" }
return @{Exe=$exe; Args=$args.Trim()}
}
# If uninstall string is quoted path to an exe with arguments
if ($s -match '^\s*"(.*?)"\s*(.*)$') {
$exePath = $matches[1]
$rest = $matches[2].Trim()
# Common Adobe silent switches: /sAll /silent /s /S /qn for MSI
if ($rest -notmatch '(?i)/sAll|/silent|/s|/S|/qn') {
# try /sAll first
$rest = ($rest + " /sAll").Trim()
}
return @{Exe=$exePath; Args=$rest}
}
# If uninstall string is unquoted path
if ($s -match '^\s*([^\s]+)\s*(.*)$') {
$exePath = $matches[1]
$rest = $matches[2].Trim()
if ($rest -notmatch '(?i)/sAll|/silent|/s|/S|/qn') {
$rest = ($rest + " /sAll").Trim()
}
return @{Exe=$exePath; Args=$rest}
}
# Fallback: return raw string as command to run via cmd /c
return @{Exe="cmd.exe"; Args="/c $s"}
}
# -------------------------
# Detect installed Acrobat Reader entries
# -------------------------
function Get-AcrobatInstallInfo {
<#
Returns array of objects:
@{ DisplayName=; UninstallString=; InstallLocation=; Publisher=; Version=; Architecture=; RegistryKey= }
#>
$results = @()
# Registry hives to search
$regPaths = @(
"HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall",
"HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall",
"HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"
)
foreach ($path in $regPaths) {
try {
$keys = Get-ChildItem -Path $path -ErrorAction SilentlyContinue
foreach ($k in $keys) {
try {
$props = Get-ItemProperty -Path $k.PSPath -ErrorAction SilentlyContinue
if ($null -eq $props) { continue }
$display = $props.DisplayName
if ($display -and $display -match 'Adobe Acrobat Reader|Acrobat Reader') {
$obj = [PSCustomObject]@{
DisplayName = $props.DisplayName
UninstallString = $props.UninstallString
InstallLocation = $props.InstallLocation
Publisher = $props.Publisher
Version = $props.DisplayVersion
RegistryKey = $k.PSPath
Architecture = if ($path -like '*WOW6432Node*') { '32-bit' } else { '64-bit' }
}
$results += $obj
}
} catch { continue }
}
} catch { continue }
}
# Also check common install folders for Acrobat Reader executables as a fallback
$possiblePaths = @(
"$env:ProgramFiles\Adobe\Acrobat Reader*",
"$env:ProgramFiles(x86)\Adobe\Acrobat Reader*"
)
foreach ($p in $possiblePaths) {
foreach ($match in Get-ChildItem -Path $p -Directory -ErrorAction SilentlyContinue) {
# If not already in results, add a fallback entry
if (-not ($results | Where-Object { $_.InstallLocation -and ($_.InstallLocation -eq $match.FullName) })) {
$exe32 = Join-Path $match.FullName 'Reader\AcroRd32.exe'
$exe64 = Join-Path $match.FullName 'Acrobat\Acrobat.exe'
if (Test-Path $exe32 -or Test-Path $exe64) {
$arch = if ($match.FullName -like "*Program Files (x86)*") { '32-bit' } else { '64-bit' }
$results += [PSCustomObject]@{
DisplayName = "Adobe Acrobat Reader (detected folder)"
UninstallString = $null
InstallLocation = $match.FullName
Publisher = "Adobe"
Version = $null
RegistryKey = $null
Architecture = $arch
}
}
}
}
}
return $results
}
# -------------------------
# Stop processes and services related to Acrobat Reader
# -------------------------
function Stop-AcrobatProcessesAndServices {
param([switch]$Force)
Log "Stopping Acrobat Reader related processes and services..." "INFO"
# Common process names
$procNames = @('AcroRd32','Acrobat','AdobeARM','AdobeUpdateService','AdobeCollabSync','RdrCEF')
foreach ($pname in $procNames) {
try {
$procs = Get-Process -Name $pname -ErrorAction SilentlyContinue
foreach ($pr in $procs) {
try {
Log "Stopping process $($pr.ProcessName) (Id $($pr.Id))" "INFO"
Stop-Process -Id $pr.Id -Force:$Force -ErrorAction Stop
Log "Stopped process Id $($pr.Id)" "INFO"
} catch {
Log "Failed to stop process $($pr.ProcessName) Id $($pr.Id): $($_.Exception.Message)" "WARN"
}
}
} catch {}
}
# Stop services that look like Adobe services
try {
$svcCandidates = Get-Service | Where-Object { $_.Name -match 'Adobe|ARM|AdobeUpdate' -or $_.DisplayName -match 'Adobe' } -ErrorAction SilentlyContinue
foreach ($svc in $svcCandidates) {
try {
if ($svc.Status -ne 'Stopped') {
Log "Stopping service $($svc.Name) ($($svc.DisplayName))" "INFO"
Stop-Service -Name $svc.Name -Force -ErrorAction Stop
Log "Stopped service $($svc.Name)" "INFO"
}
} catch {
Log "Failed to stop service $($svc.Name): $($_.Exception.Message)" "WARN"
}
}
} catch {
Log "Service enumeration failed: $($_.Exception.Message)" "WARN"
}
}
# -------------------------
# Uninstall function
# -------------------------
function Uninstall-Acrobat {
param(
[Parameter(Mandatory=$true)][PSCustomObject]$InstallInfo
)
Log "Preparing to uninstall: $($InstallInfo.DisplayName) (Arch: $($InstallInfo.Architecture))" "INFO"
if (-not $InstallInfo.UninstallString) {
Log "No uninstall string found in registry for this entry. Attempting to remove folder if present." "WARN"
if ($InstallInfo.InstallLocation -and (Test-Path $InstallInfo.InstallLocation)) {
try {
Log "Attempting to remove folder: $($InstallInfo.InstallLocation)" "INFO"
Remove-Item -Path $InstallInfo.InstallLocation -Recurse -Force -ErrorAction Stop
Log "Removed folder $($InstallInfo.InstallLocation)" "INFO"
} catch {
Log "Failed to remove folder $($InstallInfo.InstallLocation): $($_.Exception.Message)" "ERROR"
}
} else {
Log "No install location available to remove." "WARN"
}
return
}
$parsed = Parse-UninstallString -UninstallString $InstallInfo.UninstallString
$exe = $parsed.Exe
$args = $parsed.Args
Log "Uninstall command: `"$exe`" $args" "INFO"
try {
# If exe is msiexec, run directly
$startInfo = @{
FilePath = $exe
ArgumentList = $args
Wait = $true
NoNewWindow = $true
ErrorAction = 'Stop'
}
Log "Starting uninstall process..." "INFO"
Start-Process @startInfo
Log "Uninstall process completed for $($InstallInfo.DisplayName)" "INFO"
} catch {
Log "Uninstall process failed: $($_.Exception.Message)" "ERROR"
}
}
# -------------------------
# Verify uninstalled and folder removed
# -------------------------
function Verify-Uninstalled {
param([PSCustomObject]$InstallInfo)
$name = $InstallInfo.DisplayName
Log "Verifying uninstall for: $name" "INFO"
# Check registry again for matching display name
$stillInstalled = $false
try {
$all = Get-AcrobatInstallInfo
if ($all | Where-Object { $_.DisplayName -and $_.DisplayName -eq $name }) {
$stillInstalled = $true
}
} catch {
Log "Failed to re-check registry: $($_.Exception.Message)" "WARN"
}
if ($stillInstalled) {
Log "Product still present in registry: $name" "ERROR"
} else {
Log "Product not found in registry: $name" "INFO"
}
# Check install folder
if ($InstallInfo.InstallLocation) {
if (Test-Path $InstallInfo.InstallLocation) {
Log "Install folder still exists: $($InstallInfo.InstallLocation)" "ERROR"
} else {
Log "Install folder removed: $($InstallInfo.InstallLocation)" "INFO"
}
} else {
Log "No install folder recorded for this entry." "INFO"
}
}
# -------------------------
# Main flow
# -------------------------
Log "=== Adobe Acrobat Reader Uninstall Script started ===" "INFO"
$found = Get-AcrobatInstallInfo
if (-not $found -or $found.Count -eq 0) {
Log "No Adobe Acrobat Reader installations detected on this machine." "INFO"
Log "=== Script finished ===" "INFO"
exit 0
}
# Process each detected installation
foreach ($inst in $found) {
Log "Detected: $($inst.DisplayName) | Version: $($inst.Version) | Arch: $($inst.Architecture) | InstallLocation: $($inst.InstallLocation)" "INFO"
# Stop processes/services
Stop-AcrobatProcessesAndServices -Force
# Wait briefly for processes to terminate
Start-Sleep -Seconds 2
# Attempt uninstall
Uninstall-Acrobat -InstallInfo $inst
# Wait for uninstall to complete and for processes to settle
Start-Sleep -Seconds 5
# Verify
Verify-Uninstalled -InstallInfo $inst
}
Log "=== Completed processing all detected Acrobat Reader installations ===" "INFO"