Skip to content

Instantly share code, notes, and snippets.

@emilwojcik93
Last active December 29, 2025 14:31
Show Gist options
  • Select an option

  • Save emilwojcik93/369a0610a3f58d04c61898b42141713b to your computer and use it in GitHub Desktop.

Select an option

Save emilwojcik93/369a0610a3f58d04c61898b42141713b to your computer and use it in GitHub Desktop.
Complete Google Chrome Uninstaller for Windows - Auto-elevates and removes all Chrome files, registry keys, and user data. Supports WhatIf mode for safe testing. Usage: irm URL | iex or with parameters: &([ScriptBlock]::Create((irm URL))) -WhatIf -Verbose

Uninstall-GoogleChrome.ps1

Complete Google Chrome removal script for Windows. Automatically elevates to administrator privileges, tries multiple uninstall methods (winget, native setup.exe, registry, WMI) with automatic fallback, then performs comprehensive cleanup of all residual files, registry keys, scheduled tasks, and user data.

Features

  • Multiple Uninstall Methods with automatic fallback chain:

    1. winget (Windows Package Manager) - Modern, recommended
    2. Native Chrome setup.exe - Direct Chrome uninstaller (uses Stack Overflow method)
    3. Registry UninstallString - Alternative approach
    4. WMI/CIM - Last resort programmatic method
    5. Manual cleanup - Always performed to ensure complete removal
  • WhatIf Mode - Safe dry-run to test what would be removed without making changes

  • Verbose Output - Detailed progress for every operation

  • Silent Mode - Minimal output for automation scenarios

  • Comprehensive Logging - Auto-generated timestamped log files

  • Admin Auto-Elevation - Automatically requests administrator privileges

  • Multiple Calling Methods - Works via direct execution or remote irm | iex

Usage

Remote Execution (Recommended for Testing)

Simple execution (no parameters):

irm https://gist.githubusercontent.com/emilwojcik93/369a0610a3f58d04c61898b42141713b/raw/Uninstall-GoogleChrome.ps1 | iex

With parameters (ScriptBlock method):

# WhatIf mode - SAFE for testing, no changes made
&([ScriptBlock]::Create((irm https://gist.githubusercontent.com/emilwojcik93/369a0610a3f58d04c61898b42141713b/raw/Uninstall-GoogleChrome.ps1))) -WhatIf

# WhatIf with verbose output (recommended first test)
&([ScriptBlock]::Create((irm https://gist.githubusercontent.com/emilwojcik93/369a0610a3f58d04c61898b42141713b/raw/Uninstall-GoogleChrome.ps1))) -WhatIf -Verbose

# Silent mode (for automation)
&([ScriptBlock]::Create((irm https://gist.githubusercontent.com/emilwojcik93/369a0610a3f58d04c61898b42141713b/raw/Uninstall-GoogleChrome.ps1))) -Silent

# Keep user data (preserve bookmarks, passwords)
&([ScriptBlock]::Create((irm https://gist.githubusercontent.com/emilwojcik93/369a0610a3f58d04c61898b42141713b/raw/Uninstall-GoogleChrome.ps1))) -KeepUserData

# Custom log file location
&([ScriptBlock]::Create((irm https://gist.githubusercontent.com/emilwojcik93/369a0610a3f58d04c61898b42141713b/raw/Uninstall-GoogleChrome.ps1))) -LogPath "C:\Logs\chrome_removal.log"

# Combined options
&([ScriptBlock]::Create((irm https://gist.githubusercontent.com/emilwojcik93/369a0610a3f58d04c61898b42141713b/raw/Uninstall-GoogleChrome.ps1))) -WhatIf -Verbose -LogPath "C:\Temp\test.log"

# Actually uninstall (after testing with -WhatIf)
&([ScriptBlock]::Create((irm https://gist.githubusercontent.com/emilwojcik93/369a0610a3f58d04c61898b42141713b/raw/Uninstall-GoogleChrome.ps1)))

Local Execution

# Download the script first
irm https://gist.githubusercontent.com/emilwojcik93/369a0610a3f58d04c61898b42141713b/raw/Uninstall-GoogleChrome.ps1 -OutFile Uninstall-GoogleChrome.ps1

# Test in WhatIf mode
.\Uninstall-GoogleChrome.ps1 -WhatIf -Verbose

# Run with various options
.\Uninstall-GoogleChrome.ps1 -KeepUserData
.\Uninstall-GoogleChrome.ps1 -Silent
.\Uninstall-GoogleChrome.ps1

If Execution Policy Blocks the Script

Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope Process -Force; irm https://gist.githubusercontent.com/emilwojcik93/369a0610a3f58d04c61898b42141713b/raw/Uninstall-GoogleChrome.ps1 | iex

Parameters

Parameter Type Description
-WhatIf Switch Dry-run mode. Shows what would be removed without making changes. SAFE for testing.
-Verbose Switch Enable detailed output showing every operation.
-Silent Switch Minimal console output (errors only). Useful for automation.
-KeepUserData Switch Preserve user data directory (bookmarks, passwords, history, extensions).
-LogPath String Custom path for the log file. Default: $env:TEMP\ChromeUninstall_yyyyMMdd_HHmmss.log
-NoLog Switch Disable logging to file.

What Gets Removed

Uninstall Methods (tried in order)

  1. Windows Package Manager (winget)
  2. Native Chrome setup.exe with --uninstall --force-uninstall flags
  3. Registry UninstallString method
  4. WMI/CIM programmatic uninstall
  5. Manual cleanup if all above fail

Directories

  • %LOCALAPPDATA%\Google\Chrome (User Data - optional with -KeepUserData)
  • %LOCALAPPDATA%\Google\CrashReports
  • %LOCALAPPDATA%\Google\Update
  • %ProgramFiles%\Google\Chrome
  • %ProgramFiles(x86)%\Google\Chrome
  • %APPDATA%\Google
  • %ProgramData%\Google\Chrome
  • %ProgramData%\Google\CrashReports

Registry Keys

  • HKCU:\Software\Google\Chrome
  • HKCU:\Software\Google\Update
  • HKLM:\SOFTWARE\Google\Chrome
  • HKLM:\SOFTWARE\Google\Update
  • HKLM:\SOFTWARE\WOW6432Node\Google\Chrome
  • HKLM:\SOFTWARE\WOW6432Node\Google\Update
  • HKLM:\SOFTWARE\Policies\Google\Chrome
  • HKCU:\Software\Policies\Google\Chrome
  • Uninstall entries in both HKLM and HKCU

Other Components

  • Google Update services (gupdate, gupdatem)
  • Google/Chrome scheduled tasks
  • Desktop and Start Menu shortcuts
  • Temporary files (%TEMP%\chrome*, %TEMP%\scoped*)

Exit Codes

Code Meaning
0 Success (Chrome removed or not installed)
1 Chrome found but removal completed with warnings
2 Admin elevation failed or denied
3 Chrome processes locked and couldn't be stopped

Examples

Test First (Recommended)

# See what would be removed without making changes
&([ScriptBlock]::Create((irm https://gist.githubusercontent.com/emilwojcik93/369a0610a3f58d04c61898b42141713b/raw/Uninstall-GoogleChrome.ps1))) -WhatIf -Verbose

Production Use

# After testing with -WhatIf, run actual uninstall
&([ScriptBlock]::Create((irm https://gist.githubusercontent.com/emilwojcik93/369a0610a3f58d04c61898b42141713b/raw/Uninstall-GoogleChrome.ps1)))

Automation Scenario

# Silent uninstall with custom log for automation
&([ScriptBlock]::Create((irm https://gist.githubusercontent.com/emilwojcik93/369a0610a3f58d04c61898b42141713b/raw/Uninstall-GoogleChrome.ps1))) -Silent -LogPath "C:\Logs\chrome_uninstall_$(Get-Date -Format 'yyyyMMdd').log"

Notes

  • Requires Administrator Privileges: The script will automatically elevate if not running as admin
  • WhatIf Mode is Safe: Use -WhatIf to test on systems where Chrome needs to remain installed
  • Profile Data: User data includes bookmarks, passwords, history, and extensions
  • Chrome Sync: Data in your Google account (if using Chrome Sync) is NOT affected
  • Other Google Software: Only Chrome is removed. Google Drive, Earth, etc. remain unchanged
  • Reinstallation: You can reinstall Chrome anytime from google.com/chrome

Technical Details

  • Version: 1.0
  • PowerShell: 5.1 or higher recommended
  • Tested on: Windows 10 Build 26200, Windows 11
  • Based on: Stack Overflow solutions and comprehensive Chrome removal guide

Related Gists

Author

Emil Wojcik (@emilwojcik93)

License

This script is provided as-is without warranty. Use at your own risk.

<#
.SYNOPSIS
Complete Google Chrome uninstaller for Windows with comprehensive cleanup.
.DESCRIPTION
This script completely removes Google Chrome from Windows systems including:
- Chrome application files
- User data (bookmarks, history, passwords, extensions)
- Registry keys and policies
- Scheduled tasks
- Google Update services
- Shortcuts and temporary files
The script automatically elevates to administrator privileges and uses multiple
uninstall methods with automatic fallback:
1. winget (Windows Package Manager) - Modern, recommended
2. Native Chrome setup.exe - Direct Chrome uninstaller
3. Registry UninstallString - Alternative approach
4. WMI/CIM - Last resort programmatic method
5. Manual cleanup - Always performed to ensure complete removal
.PARAMETER WhatIf
Dry-run mode. Scans and reports what would be removed without making any changes.
SAFE for testing on systems where Chrome needs to remain installed.
.PARAMETER Verbose
Enable detailed output showing every operation and file/registry key being processed.
.PARAMETER Silent
Silent mode with minimal console output (errors only). Useful for automation.
Logging to file still occurs unless -NoLog is specified.
.PARAMETER KeepUserData
Preserve user data directory (bookmarks, passwords, history, extensions).
Only removes the Chrome application and system-level components.
.PARAMETER LogPath
Custom path for the log file. Default: $env:TEMP\ChromeUninstall_yyyyMMdd_HHmmss.log
.PARAMETER NoLog
Disable logging to file. All operations will still be shown on console (unless -Silent).
.EXAMPLE
.\Uninstall-GoogleChrome.ps1 -WhatIf
Scan and report what would be removed without making any changes (SAFE for testing).
.EXAMPLE
.\Uninstall-GoogleChrome.ps1 -WhatIf -Verbose
Detailed scan with verbose output showing all detected components.
.EXAMPLE
.\Uninstall-GoogleChrome.ps1
Uninstall Chrome completely with default settings.
.EXAMPLE
.\Uninstall-GoogleChrome.ps1 -KeepUserData
Uninstall Chrome but preserve bookmarks, passwords, and other user data.
.EXAMPLE
.\Uninstall-GoogleChrome.ps1 -Silent -LogPath "C:\Logs\chrome_removal.log"
Silent uninstall with custom log file location (for automation).
.EXAMPLE
irm https://gist.githubusercontent.com/emilwojcik93/[GIST_ID]/raw/Uninstall-GoogleChrome.ps1 | iex
Remote execution via Invoke-RestMethod (simple, no parameters).
.EXAMPLE
&([ScriptBlock]::Create((irm https://gist.githubusercontent.com/emilwojcik93/[GIST_ID]/raw/Uninstall-GoogleChrome.ps1))) -WhatIf -Verbose
Remote execution with parameters using ScriptBlock pattern.
.NOTES
File Name : Uninstall-GoogleChrome.ps1
Author : Emil Wojcik (emilwojcik93)
Prerequisite : PowerShell 5.1 or higher
Version : 1.0
Date : 2025-12-29
Exit Codes:
0 - Success (Chrome removed or not installed)
1 - Chrome found but removal failed
2 - Admin elevation failed or denied
3 - Chrome processes locked and couldn't be stopped
.LINK
https://gist.github.com/emilwojcik93
#>
[CmdletBinding(SupportsShouldProcess=$true)]
param(
[Parameter(Mandatory=$false)]
[switch]$Silent,
[Parameter(Mandatory=$false)]
[switch]$KeepUserData,
[Parameter(Mandatory=$false)]
[ValidateScript({
$parentDir = Split-Path $_ -Parent
if ($parentDir -and !(Test-Path $parentDir)) {
throw "Directory does not exist: $parentDir"
}
$true
})]
[string]$LogPath,
[Parameter(Mandatory=$false)]
[switch]$NoLog
)
# Script version
$script:ScriptVersion = "1.0"
$script:ScriptName = "Chrome Uninstaller"
# Global variables
$script:LogFile = $null
$script:ChromeDetected = $false
$script:ChromeVersion = $null
$script:ChromePath = $null
$script:IsWhatIfMode = $false
$script:IsVerboseMode = $false
$script:IsSilentMode = $Silent.IsPresent
$script:ComponentsFound = @{
Processes = @()
Services = @()
Directories = @()
RegistryKeys = @()
ScheduledTasks = @()
Shortcuts = @()
}
#region Helper Functions
function Write-Log {
<#
.SYNOPSIS
Dual-output logging function (console + file)
#>
[CmdletBinding()]
param(
[Parameter(Mandatory=$true)]
[string]$Message,
[Parameter(Mandatory=$false)]
[ValidateSet('INFO', 'SUCCESS', 'WARNING', 'ERROR', 'VERBOSE')]
[string]$Level = 'INFO',
[Parameter(Mandatory=$false)]
[ConsoleColor]$Color
)
$timestamp = Get-Date -Format 'yyyy-MM-dd HH:mm:ss'
$logMessage = "[$timestamp] [$Level] $Message"
# Write to log file if enabled
if (-not $NoLog -and $script:LogFile) {
try {
Add-Content -Path $script:LogFile -Value $logMessage -ErrorAction SilentlyContinue
} catch {
# Silently ignore log file errors
}
}
# Write to console unless Silent mode (except for errors)
if (-not $IsSilentMode -or $Level -eq 'ERROR') {
# Skip verbose messages unless in verbose mode
if ($Level -eq 'VERBOSE' -and -not $IsVerboseMode) {
return
}
# Set color based on level
if (-not $Color) {
$Color = switch ($Level) {
'SUCCESS' { 'Green' }
'WARNING' { 'Yellow' }
'ERROR' { 'Red' }
'VERBOSE' { 'Gray' }
default { 'White' }
}
}
Write-Host "[$Level] $Message" -ForegroundColor $Color
}
}
function Initialize-Logging {
<#
.SYNOPSIS
Initialize the logging system
#>
if ($NoLog) {
Write-Log "Logging to file is disabled" -Level INFO
return
}
if ($LogPath) {
$script:LogFile = $LogPath
} else {
$timestamp = Get-Date -Format 'yyyyMMdd_HHmmss'
$script:LogFile = Join-Path $env:TEMP "ChromeUninstall_$timestamp.log"
}
try {
# Create log file
$null = New-Item -Path $script:LogFile -ItemType File -Force -ErrorAction Stop
# Write header
$header = @"
================================================================================
$script:ScriptName v$script:ScriptVersion
Started: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')
User: $env:USERNAME
Computer: $env:COMPUTERNAME
OS: $(Get-WmiObject Win32_OperatingSystem | Select-Object -ExpandProperty Caption)
PowerShell: $($PSVersionTable.PSVersion)
Mode: $(if($IsWhatIfMode){'WhatIf (Dry-Run)'}else{'Execute'})
================================================================================
"@
Add-Content -Path $script:LogFile -Value $header
if (-not $IsSilentMode) {
Write-Host "Logging to: $script:LogFile" -ForegroundColor Cyan
}
} catch {
Write-Host "[WARNING] Could not create log file: $_" -ForegroundColor Yellow
$script:LogFile = $null
}
}
function Test-AdminRights {
<#
.SYNOPSIS
Check if running with administrator privileges
#>
$currentPrincipal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())
return $currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
}
function Invoke-Elevate {
<#
.SYNOPSIS
Elevate the script to administrator privileges
#>
Write-Log "This script requires administrator privileges" -Level WARNING
Write-Log "Attempting to relaunch with elevation..." -Level INFO
# Build argument list from bound parameters
$argList = @()
$PSBoundParameters.GetEnumerator() | ForEach-Object {
$argList += if ($_.Value -is [switch] -and $_.Value) {
"-$($_.Key)"
} elseif ($_.Value) {
"-$($_.Key) `"$($_.Value)`""
}
}
# Detect execution context
$script = if ($PSCommandPath) {
# Local file execution
"& { & `"$($PSCommandPath)`" $argList }"
} else {
# Remote execution via irm - reconstruct ScriptBlock
# Note: This will work if the script was called via ScriptBlock pattern
Write-Log "Remote execution detected - parameters will be preserved" -Level VERBOSE
# For remote elevation, we need to embed the URL or pass it through
# Since we can't determine the original URL, user needs to run with admin from the start
# or we can try to re-execute with parameters
Write-Log "For remote execution, please run PowerShell as Administrator first" -Level ERROR
exit 2
}
# Determine PowerShell command
$powershellcmd = if (Get-Command pwsh -ErrorAction SilentlyContinue) { "pwsh" } else { "powershell" }
# Determine terminal/console to use
$processCmd = if (Get-Command wt.exe -ErrorAction SilentlyContinue) { "wt.exe" } else { $powershellcmd }
try {
$process = Start-Process $processCmd -ArgumentList "$powershellcmd -ExecutionPolicy Bypass -NoProfile -Command $script" -Verb RunAs -PassThru
Write-Log "Script relaunched with elevation" -Level INFO
exit 0
} catch {
Write-Log "Failed to elevate privileges: $($_.Exception.Message)" -Level ERROR
exit 2
}
}
function Find-ChromeInstallation {
<#
.SYNOPSIS
Detect Chrome installation using multiple methods
#>
Write-Log "Detecting Chrome installation..." -Level INFO
$chromeInfo = @{
Installed = $false
Version = $null
InstallPath = $null
RegistryPath = $null
UninstallString = $null
}
# Method 1: Check registry (most reliable)
$registryPaths = @(
'HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Google Chrome',
'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Google Chrome',
'HKCU:\Software\Microsoft\Windows\CurrentVersion\Uninstall\Google Chrome'
)
foreach ($regPath in $registryPaths) {
if (Test-Path $regPath) {
Write-Log "Found Chrome registry entry: $regPath" -Level VERBOSE
try {
$regKey = Get-ItemProperty -Path $regPath -ErrorAction Stop
$chromeInfo.Installed = $true
$chromeInfo.Version = $regKey.Version
$chromeInfo.RegistryPath = $regPath
$chromeInfo.UninstallString = $regKey.UninstallString
# Try to determine install path from DisplayIcon or InstallLocation
if ($regKey.DisplayIcon) {
$chromeInfo.InstallPath = Split-Path (Split-Path $regKey.DisplayIcon -Parent) -Parent
} elseif ($regKey.InstallLocation) {
$chromeInfo.InstallPath = $regKey.InstallLocation
}
Write-Log "Chrome detected: Version $($chromeInfo.Version)" -Level SUCCESS
break
} catch {
$errMsg = $_.Exception.Message
Write-Log "Error reading registry: $errMsg" -Level VERBOSE
}
}
}
# Method 2: Check file system
if (-not $chromeInfo.Installed) {
$installPaths = @(
"${env:ProgramFiles(x86)}\Google\Chrome\Application",
"$env:ProgramFiles\Google\Chrome\Application",
"$env:LOCALAPPDATA\Google\Chrome\Application"
)
foreach ($path in $installPaths) {
if (Test-Path $path) {
Write-Log "Found Chrome installation directory: $path" -Level VERBOSE
$chromeInfo.Installed = $true
$chromeInfo.InstallPath = $path
# Try to get version from chrome.exe
$chromeExe = Join-Path $path "chrome.exe"
if (Test-Path $chromeExe) {
try {
$versionInfo = (Get-Item $chromeExe).VersionInfo
$chromeInfo.Version = $versionInfo.FileVersion
Write-Log "Chrome detected: Version $($chromeInfo.Version)" -Level SUCCESS
} catch {
Write-Log "Found Chrome but couldn't determine version" -Level WARNING
}
}
break
}
}
}
if (-not $chromeInfo.Installed) {
Write-Log "Chrome is not installed on this system" -Level INFO
} else {
Write-Log "Installation path: $($chromeInfo.InstallPath)" -Level VERBOSE
}
return $chromeInfo
}
function Get-ChromeComponents {
<#
.SYNOPSIS
Scan all Chrome-related components on the system
#>
Write-Log "Scanning for Chrome components..." -Level INFO
# Check for running processes
$processes = Get-Process -Name chrome -ErrorAction SilentlyContinue
if ($processes) {
$script:ComponentsFound.Processes = $processes
Write-Log "Found $($processes.Count) Chrome process(es) running" -Level VERBOSE
}
# Check for services
$services = @('gupdate', 'gupdatem') | ForEach-Object {
Get-Service -Name $_ -ErrorAction SilentlyContinue
} | Where-Object { $_ }
if ($services) {
$script:ComponentsFound.Services = $services
Write-Log "Found $($services.Count) Google Update service(s)" -Level VERBOSE
}
# Check for directories
$directories = @(
"$env:LOCALAPPDATA\Google\Chrome",
"$env:LOCALAPPDATA\Google\CrashReports",
"$env:LOCALAPPDATA\Google\Update",
"$env:ProgramFiles\Google\Chrome",
"${env:ProgramFiles(x86)}\Google\Chrome",
"$env:APPDATA\Google",
"$env:ProgramData\Google\Chrome",
"$env:ProgramData\Google\CrashReports"
)
foreach ($dir in $directories) {
if (Test-Path $dir) {
try {
$size = (Get-ChildItem $dir -Recurse -ErrorAction SilentlyContinue |
Measure-Object -Property Length -Sum -ErrorAction SilentlyContinue).Sum / 1MB
$script:ComponentsFound.Directories += @{
Path = $dir
SizeMB = [math]::Round($size, 2)
}
Write-Log "Found directory: $dir ($([math]::Round($size, 2)) MB)" -Level VERBOSE
} catch {
$script:ComponentsFound.Directories += @{
Path = $dir
SizeMB = 0
}
Write-Log "Found directory: $dir (size unknown)" -Level VERBOSE
}
}
}
# Check for registry keys
$registryKeys = @(
'HKCU:\Software\Google\Chrome',
'HKCU:\Software\Google\Update',
'HKLM:\SOFTWARE\Google\Chrome',
'HKLM:\SOFTWARE\Google\Update',
'HKLM:\SOFTWARE\WOW6432Node\Google\Chrome',
'HKLM:\SOFTWARE\WOW6432Node\Google\Update',
'HKLM:\SOFTWARE\Policies\Google\Chrome',
'HKCU:\Software\Policies\Google\Chrome',
'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Google Chrome',
'HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Google Chrome',
'HKCU:\Software\Microsoft\Windows\CurrentVersion\Uninstall\Google Chrome'
)
foreach ($key in $registryKeys) {
if (Test-Path $key) {
$script:ComponentsFound.RegistryKeys += $key
Write-Log "Found registry key: $key" -Level VERBOSE
}
}
# Check for scheduled tasks
try {
$tasks = Get-ScheduledTask -ErrorAction SilentlyContinue |
Where-Object { $_.TaskPath -like "*Google*" -or $_.TaskName -like "*Chrome*" -or $_.TaskName -like "*Google*" }
if ($tasks) {
$script:ComponentsFound.ScheduledTasks = $tasks
Write-Log "Found $($tasks.Count) Google/Chrome scheduled task(s)" -Level VERBOSE
}
} catch {
$errMsg = $_.Exception.Message
Write-Log "Could not scan scheduled tasks: $errMsg" -Level VERBOSE
}
# Check for shortcuts
$shortcutLocations = @(
"$env:USERPROFILE\Desktop",
"$env:APPDATA\Microsoft\Windows\Start Menu\Programs",
"$env:ProgramData\Microsoft\Windows\Start Menu\Programs",
"$env:PUBLIC\Desktop"
)
foreach ($location in $shortcutLocations) {
if (Test-Path $location) {
$shortcuts = Get-ChildItem -Path $location -Filter "*Chrome*.lnk" -Recurse -ErrorAction SilentlyContinue
if ($shortcuts) {
$script:ComponentsFound.Shortcuts += $shortcuts
Write-Log "Found $($shortcuts.Count) shortcut(s) in $location" -Level VERBOSE
}
}
}
# Summary
$totalComponents = $script:ComponentsFound.Processes.Count +
$script:ComponentsFound.Services.Count +
$script:ComponentsFound.Directories.Count +
$script:ComponentsFound.RegistryKeys.Count +
$script:ComponentsFound.ScheduledTasks.Count +
$script:ComponentsFound.Shortcuts.Count
Write-Log "Component scan complete: $totalComponents item(s) found" -Level INFO
return $totalComponents -gt 0
}
function Stop-ChromeProcesses {
<#
.SYNOPSIS
Stop all running Chrome processes
#>
$processes = Get-Process -Name chrome -ErrorAction SilentlyContinue
if (-not $processes) {
Write-Log "No Chrome processes running" -Level VERBOSE
return $true
}
if ($IsWhatIfMode) {
Write-Log "Would stop $($processes.Count) Chrome process(es)" -Level INFO
return $true
}
Write-Log "Stopping $($processes.Count) Chrome process(es)..." -Level INFO
try {
$processes | Stop-Process -Force -ErrorAction Stop
Start-Sleep -Seconds 2
# Verify processes stopped
$remainingProcesses = Get-Process -Name chrome -ErrorAction SilentlyContinue
if ($remainingProcesses) {
Write-Log "Warning: $($remainingProcesses.Count) Chrome process(es) could not be stopped" -Level WARNING
return $false
}
Write-Log "All Chrome processes stopped successfully" -Level SUCCESS
return $true
} catch {
$errMsg = $_.Exception.Message
Write-Log "Error stopping Chrome processes: $errMsg" -Level ERROR
return $false
}
}
function Stop-GoogleServices {
<#
.SYNOPSIS
Stop Google Update services
#>
$serviceNames = @('gupdate', 'gupdatem')
$stoppedCount = 0
foreach ($serviceName in $serviceNames) {
$service = Get-Service -Name $serviceName -ErrorAction SilentlyContinue
if ($service) {
if ($IsWhatIfMode) {
Write-Log "Would stop service: $serviceName" -Level INFO
$stoppedCount++
} else {
try {
if ($service.Status -eq 'Running') {
Write-Log "Stopping service: $serviceName" -Level VERBOSE
Stop-Service -Name $serviceName -Force -ErrorAction Stop
$stoppedCount++
} else {
Write-Log "Service $serviceName is already stopped" -Level VERBOSE
}
} catch {
$errMsg = $_.Exception.Message
Write-Log "Could not stop service ${serviceName}: $errMsg" -Level WARNING
}
}
}
}
if ($stoppedCount -gt 0) {
Write-Log "Stopped $stoppedCount Google Update service(s)" -Level SUCCESS
}
return $true
}
function Invoke-WingetUninstall {
<#
.SYNOPSIS
Try to uninstall Chrome using winget
#>
Write-Log "Attempting uninstall via winget..." -Level INFO
# Check if winget is available
$winget = Get-Command winget -ErrorAction SilentlyContinue
if (-not $winget) {
Write-Log "winget is not available on this system" -Level VERBOSE
return $false
}
Write-Log "winget detected: $($winget.Version)" -Level VERBOSE
if ($IsWhatIfMode) {
Write-Log "Would execute: winget uninstall --id Google.Chrome --silent --force" -Level INFO
return $true
}
try {
Write-Log "Executing: winget uninstall --id Google.Chrome --silent --force --accept-source-agreements" -Level VERBOSE
$output = & winget uninstall --id Google.Chrome --silent --force --accept-source-agreements 2>&1
if ($LASTEXITCODE -eq 0) {
Write-Log "Chrome uninstalled successfully via winget" -Level SUCCESS
return $true
} else {
Write-Log "winget uninstall failed with exit code: $LASTEXITCODE" -Level WARNING
Write-Log "Output: $output" -Level VERBOSE
return $false
}
} catch {
$errMsg = $_.Exception.Message
Write-Log "Error during winget uninstall: $errMsg" -Level WARNING
return $false
}
}
function Invoke-NativeUninstall {
<#
.SYNOPSIS
Try to uninstall Chrome using native setup.exe
#>
param(
[Parameter(Mandatory=$true)]
[hashtable]$ChromeInfo
)
Write-Log "Attempting uninstall via native setup.exe..." -Level INFO
# Try to get version from registry
try {
$version = (Get-ItemProperty -Path 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Google Chrome' -ErrorAction Stop).Version
if ($version) {
$uninstallerPath = "${env:ProgramFiles(x86)}\Google\Chrome\Application\$version\Installer\setup.exe"
if (Test-Path $uninstallerPath) {
Write-Log "Found native uninstaller: $uninstallerPath" -Level VERBOSE
if ($IsWhatIfMode) {
Write-Log "Would execute: $uninstallerPath --uninstall --multi-install --chrome --system-level --force-uninstall" -Level INFO
return $true
}
try {
Write-Log "Executing native uninstaller..." -Level VERBOSE
$process = Start-Process -FilePath $uninstallerPath -ArgumentList "--uninstall --multi-install --chrome --system-level --force-uninstall" -Wait -PassThru -NoNewWindow
if ($process.ExitCode -eq 0 -or $process.ExitCode -eq 19) {
# Exit code 19 means "already uninstalled" which is OK
Write-Log "Chrome uninstalled successfully via native setup.exe" -Level SUCCESS
return $true
} else {
Write-Log "Native uninstaller failed with exit code: $($process.ExitCode)" -Level WARNING
return $false
}
} catch {
$errMsg = $_.Exception.Message
Write-Log "Error executing native uninstaller: $errMsg" -Level WARNING
return $false
}
}
}
} catch {
$errMsg = $_.Exception.Message
Write-Log "Could not locate native uninstaller: $errMsg" -Level VERBOSE
}
return $false
}
function Invoke-RegistryUninstall {
<#
.SYNOPSIS
Try to uninstall Chrome using registry UninstallString
#>
param(
[Parameter(Mandatory=$true)]
[hashtable]$ChromeInfo
)
Write-Log "Attempting uninstall via registry UninstallString..." -Level INFO
if ($ChromeInfo.UninstallString) {
Write-Log "Found UninstallString: $($ChromeInfo.UninstallString)" -Level VERBOSE
if ($IsWhatIfMode) {
Write-Log "Would execute: $($ChromeInfo.UninstallString) --force-uninstall" -Level INFO
return $true
}
try {
# Parse the uninstall string
$uninstallCmd = $ChromeInfo.UninstallString
if ($uninstallCmd -match '"([^"]+)"') {
$exePath = $matches[1]
$args = "--force-uninstall"
Write-Log "Executing registry uninstaller..." -Level VERBOSE
$process = Start-Process -FilePath $exePath -ArgumentList $args -Wait -PassThru -NoNewWindow
if ($process.ExitCode -eq 0 -or $process.ExitCode -eq 19) {
Write-Log "Chrome uninstalled successfully via registry method" -Level SUCCESS
return $true
} else {
Write-Log "Registry uninstaller failed with exit code: $($process.ExitCode)" -Level WARNING
return $false
}
}
} catch {
$errMsg = $_.Exception.Message
Write-Log "Error executing registry uninstaller: $errMsg" -Level WARNING
return $false
}
}
Write-Log "No registry UninstallString found" -Level VERBOSE
return $false
}
function Invoke-WMIUninstall {
<#
.SYNOPSIS
Try to uninstall Chrome using WMI/CIM
#>
Write-Log "Attempting uninstall via WMI/CIM..." -Level INFO
try {
$chrome = Get-CimInstance -ClassName Win32_Product -ErrorAction Stop |
Where-Object { $_.Name -eq 'Google Chrome' }
if ($chrome) {
Write-Log "Found Chrome via WMI" -Level VERBOSE
if ($IsWhatIfMode) {
Write-Log "Would invoke WMI Uninstall method" -Level INFO
return $true
}
Write-Log "Invoking WMI Uninstall method (this may take a while)..." -Level VERBOSE
$result = Invoke-CimMethod -InputObject $chrome -MethodName Uninstall
if ($result.ReturnValue -eq 0) {
Write-Log "Chrome uninstalled successfully via WMI" -Level SUCCESS
return $true
} else {
Write-Log "WMI uninstall failed with return value: $($result.ReturnValue)" -Level WARNING
return $false
}
} else {
Write-Log "Chrome not found in WMI" -Level VERBOSE
return $false
}
} catch {
$errMsg = $_.Exception.Message
Write-Log "Error during WMI uninstall: $errMsg" -Level WARNING
return $false
}
}
function Invoke-ChromeUninstall {
<#
.SYNOPSIS
Main uninstall function with fallback chain
#>
param(
[Parameter(Mandatory=$true)]
[hashtable]$ChromeInfo
)
Write-Log "Starting Chrome uninstall process..." -Level INFO
Write-Log "Uninstall method priority: winget -> native setup.exe -> registry -> WMI -> manual" -Level INFO
# Stop processes and services first
if (-not (Stop-ChromeProcesses)) {
if (-not $IsWhatIfMode) {
Write-Log "Warning: Some Chrome processes could not be stopped" -Level WARNING
Write-Log "Uninstall may fail or require a system restart" -Level WARNING
}
}
Stop-GoogleServices
# Try each uninstall method in order
$uninstallMethods = @(
@{ Name = "winget"; Function = { Invoke-WingetUninstall } },
@{ Name = "Native setup.exe"; Function = { Invoke-NativeUninstall -ChromeInfo $ChromeInfo } },
@{ Name = "Registry UninstallString"; Function = { Invoke-RegistryUninstall -ChromeInfo $ChromeInfo } },
@{ Name = "WMI/CIM"; Function = { Invoke-WMIUninstall } }
)
$uninstallSuccessful = $false
foreach ($method in $uninstallMethods) {
Write-Log "Trying method: $($method.Name)" -Level VERBOSE
if (& $method.Function) {
Write-Log "Uninstall successful using: $($method.Name)" -Level SUCCESS
$uninstallSuccessful = $true
break
} else {
Write-Log "Method failed: $($method.Name), trying next method..." -Level VERBOSE
}
}
if (-not $uninstallSuccessful -and -not $IsWhatIfMode) {
Write-Log "All uninstall methods failed, proceeding with manual cleanup only" -Level WARNING
}
return $uninstallSuccessful
}
function Remove-ChromeDirectories {
<#
.SYNOPSIS
Remove all Chrome-related directories
#>
Write-Log "Removing Chrome directories..." -Level INFO
$directories = @(
"$env:LOCALAPPDATA\Google\CrashReports",
"$env:LOCALAPPDATA\Google\Update",
"$env:ProgramFiles\Google\Chrome",
"${env:ProgramFiles(x86)}\Google\Chrome",
"$env:APPDATA\Google",
"$env:ProgramData\Google\Chrome",
"$env:ProgramData\Google\CrashReports",
"${env:ProgramFiles(x86)}\Google\Update",
"$env:ProgramFiles\Google\Update"
)
# Add user data directory unless KeepUserData is specified
if (-not $KeepUserData) {
$directories = @("$env:LOCALAPPDATA\Google\Chrome") + $directories
} else {
Write-Log "Preserving user data directory (KeepUserData flag set)" -Level INFO
}
$removedCount = 0
foreach ($dir in $directories) {
if (Test-Path $dir) {
if ($IsWhatIfMode) {
try {
$size = (Get-ChildItem $dir -Recurse -ErrorAction SilentlyContinue |
Measure-Object -Property Length -Sum -ErrorAction SilentlyContinue).Sum / 1MB
Write-Log "Would remove: $dir ($([math]::Round($size, 2)) MB)" -Level INFO
} catch {
Write-Log "Would remove: $dir" -Level INFO
}
$removedCount++
} else {
try {
Write-Log "Removing: $dir" -Level VERBOSE
Remove-Item -Path $dir -Recurse -Force -ErrorAction Stop
Write-Log "Removed: $dir" -Level SUCCESS
$removedCount++
} catch {
$errMsg = $_.Exception.Message
Write-Log "Could not remove $dir : $errMsg" -Level WARNING
}
}
} else {
Write-Log "Directory not found: $dir" -Level VERBOSE
}
}
Write-Log "Removed $removedCount director(ies)" -Level SUCCESS
}
function Remove-ChromeRegistry {
<#
.SYNOPSIS
Remove all Chrome-related registry keys
#>
Write-Log "Removing Chrome registry keys..." -Level INFO
$registryKeys = @(
'HKCU:\Software\Google\Chrome',
'HKCU:\Software\Google\Update',
'HKLM:\SOFTWARE\Google\Chrome',
'HKLM:\SOFTWARE\Google\Update',
'HKLM:\SOFTWARE\WOW6432Node\Google\Chrome',
'HKLM:\SOFTWARE\WOW6432Node\Google\Update',
'HKLM:\SOFTWARE\Policies\Google\Chrome',
'HKCU:\Software\Policies\Google\Chrome',
'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Google Chrome',
'HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Google Chrome',
'HKCU:\Software\Microsoft\Windows\CurrentVersion\Uninstall\Google Chrome'
)
$removedCount = 0
foreach ($key in $registryKeys) {
if (Test-Path $key) {
if ($IsWhatIfMode) {
Write-Log "Would remove registry key: $key" -Level INFO
$removedCount++
} else {
try {
Write-Log "Removing registry key: $key" -Level VERBOSE
Remove-Item -Path $key -Recurse -Force -ErrorAction Stop
Write-Log "Removed: $key" -Level SUCCESS
$removedCount++
} catch {
$errMsg = $_.Exception.Message
Write-Log "Could not remove $key : $errMsg" -Level WARNING
}
}
} else {
Write-Log "Registry key not found: $key" -Level VERBOSE
}
}
Write-Log "Removed $removedCount registry key(s)" -Level SUCCESS
}
function Remove-ChromeScheduledTasks {
<#
.SYNOPSIS
Remove Chrome/Google scheduled tasks
#>
Write-Log "Removing scheduled tasks..." -Level INFO
try {
$tasks = Get-ScheduledTask -ErrorAction SilentlyContinue |
Where-Object { $_.TaskPath -like "*Google*" -or $_.TaskName -like "*Chrome*" -or $_.TaskName -like "*Google*" }
if (-not $tasks) {
Write-Log "No Chrome/Google scheduled tasks found" -Level VERBOSE
return
}
$removedCount = 0
foreach ($task in $tasks) {
if ($IsWhatIfMode) {
Write-Log "Would remove scheduled task: $($task.TaskName)" -Level INFO
$removedCount++
} else {
try {
Write-Log "Removing scheduled task: $($task.TaskName)" -Level VERBOSE
Unregister-ScheduledTask -TaskName $task.TaskName -TaskPath $task.TaskPath -Confirm:$false -ErrorAction Stop
Write-Log "Removed: $($task.TaskName)" -Level SUCCESS
$removedCount++
} catch {
$errMsg = $_.Exception.Message
Write-Log "Could not remove task $($task.TaskName): $errMsg" -Level WARNING
}
}
}
Write-Log "Removed $removedCount scheduled task(s)" -Level SUCCESS
} catch {
$errMsg = $_.Exception.Message
Write-Log "Error scanning scheduled tasks: $errMsg" -Level WARNING
}
}
function Remove-ChromeShortcuts {
<#
.SYNOPSIS
Remove Chrome desktop and start menu shortcuts
#>
Write-Log "Removing shortcuts..." -Level INFO
$shortcutLocations = @(
"$env:USERPROFILE\Desktop",
"$env:APPDATA\Microsoft\Windows\Start Menu\Programs",
"$env:ProgramData\Microsoft\Windows\Start Menu\Programs",
"$env:PUBLIC\Desktop"
)
$removedCount = 0
foreach ($location in $shortcutLocations) {
if (Test-Path $location) {
$shortcuts = Get-ChildItem -Path $location -Filter "*Chrome*.lnk" -Recurse -ErrorAction SilentlyContinue
foreach ($shortcut in $shortcuts) {
if ($IsWhatIfMode) {
Write-Log "Would remove shortcut: $($shortcut.FullName)" -Level INFO
$removedCount++
} else {
try {
Write-Log "Removing shortcut: $($shortcut.FullName)" -Level VERBOSE
Remove-Item -Path $shortcut.FullName -Force -ErrorAction Stop
Write-Log "Removed: $($shortcut.Name)" -Level SUCCESS
$removedCount++
} catch {
$errMsg = $_.Exception.Message
Write-Log "Could not remove $($shortcut.Name): $errMsg" -Level WARNING
}
}
}
}
}
Write-Log "Removed $removedCount shortcut(s)" -Level SUCCESS
}
function Remove-ChromeTempFiles {
<#
.SYNOPSIS
Remove Chrome temporary files
#>
Write-Log "Cleaning temporary files..." -Level INFO
$tempPatterns = @(
"$env:TEMP\chrome*",
"$env:TEMP\scoped*"
)
$removedCount = 0
foreach ($pattern in $tempPatterns) {
$items = Get-ChildItem -Path (Split-Path $pattern -Parent) -Filter (Split-Path $pattern -Leaf) -ErrorAction SilentlyContinue
foreach ($item in $items) {
if ($IsWhatIfMode) {
Write-Log "Would remove: $($item.FullName)" -Level VERBOSE
$removedCount++
} else {
try {
Remove-Item -Path $item.FullName -Recurse -Force -ErrorAction Stop
Write-Log "Removed: $($item.Name)" -Level VERBOSE
$removedCount++
} catch {
$errMsg = $_.Exception.Message
Write-Log "Could not remove $($item.Name): $errMsg" -Level VERBOSE
}
}
}
}
if ($removedCount -gt 0) {
Write-Log "Cleaned $removedCount temporary file(s)" -Level SUCCESS
} else {
Write-Log "No temporary files to clean" -Level VERBOSE
}
}
function Remove-GoogleUpdateServices {
<#
.SYNOPSIS
Remove Google Update services
#>
Write-Log "Removing Google Update services..." -Level INFO
$serviceNames = @('gupdate', 'gupdatem')
$removedCount = 0
foreach ($serviceName in $serviceNames) {
$service = Get-Service -Name $serviceName -ErrorAction SilentlyContinue
if ($service) {
if ($IsWhatIfMode) {
Write-Log "Would remove service: $serviceName" -Level INFO
$removedCount++
} else {
try {
# Stop service first if running
if ($service.Status -eq 'Running') {
Stop-Service -Name $serviceName -Force -ErrorAction SilentlyContinue
}
Write-Log "Removing service: $serviceName" -Level VERBOSE
$output = sc.exe delete $serviceName 2>&1
if ($LASTEXITCODE -eq 0) {
Write-Log "Removed service: $serviceName" -Level SUCCESS
$removedCount++
} else {
Write-Log "Could not remove service $serviceName : $output" -Level WARNING
}
} catch {
$errMsg = $_.Exception.Message
Write-Log "Error removing service $serviceName : $errMsg" -Level WARNING
}
}
} else {
Write-Log "Service not found: $serviceName" -Level VERBOSE
}
}
if ($removedCount -gt 0) {
Write-Log "Removed $removedCount service(s)" -Level SUCCESS
}
}
function Invoke-ComprehensiveCleanup {
<#
.SYNOPSIS
Perform comprehensive cleanup of all Chrome components
#>
Write-Log "Starting comprehensive cleanup..." -Level INFO
Remove-ChromeDirectories
Remove-ChromeRegistry
Remove-ChromeScheduledTasks
Remove-ChromeShortcuts
Remove-ChromeTempFiles
Remove-GoogleUpdateServices
Write-Log "Comprehensive cleanup complete" -Level SUCCESS
}
function Test-ChromeRemoval {
<#
.SYNOPSIS
Verify that Chrome has been completely removed
#>
Write-Log "Verifying Chrome removal..." -Level INFO
$issuesFound = @()
# Check for running processes
$processes = Get-Process -Name chrome -ErrorAction SilentlyContinue
if ($processes) {
$issuesFound += "Chrome processes still running: $($processes.Count)"
Write-Log "WARNING: $($processes.Count) Chrome process(es) still running" -Level WARNING
} else {
Write-Log "✓ No Chrome processes running" -Level SUCCESS
}
# Check key directories
$keyDirs = @(
"$env:LOCALAPPDATA\Google\Chrome",
"$env:ProgramFiles\Google\Chrome",
"${env:ProgramFiles(x86)}\Google\Chrome"
)
$remainingDirs = @()
foreach ($dir in $keyDirs) {
if (Test-Path $dir) {
$remainingDirs += $dir
$issuesFound += "Directory still exists: $dir"
}
}
if ($remainingDirs.Count -eq 0) {
Write-Log "✓ All Chrome directories removed" -Level SUCCESS
} else {
Write-Log "WARNING: $($remainingDirs.Count) director(ies) still exist" -Level WARNING
foreach ($dir in $remainingDirs) {
Write-Log " - $dir" -Level WARNING
}
}
# Check key registry entries
$keyRegKeys = @(
'HKCU:\Software\Google\Chrome',
'HKLM:\SOFTWARE\Google\Chrome',
'HKLM:\SOFTWARE\WOW6432Node\Google\Chrome'
)
$remainingKeys = @()
foreach ($key in $keyRegKeys) {
if (Test-Path $key) {
$remainingKeys += $key
$issuesFound += "Registry key still exists: $key"
}
}
if ($remainingKeys.Count -eq 0) {
Write-Log "✓ All Chrome registry keys removed" -Level SUCCESS
} else {
Write-Log "WARNING: $($remainingKeys.Count) registry key(s) still exist" -Level WARNING
foreach ($key in $remainingKeys) {
Write-Log " - $key" -Level WARNING
}
}
# Check for services
$services = @('gupdate', 'gupdatem') | ForEach-Object {
Get-Service -Name $_ -ErrorAction SilentlyContinue
} | Where-Object { $_ }
if ($services) {
Write-Log "WARNING: $($services.Count) Google Update service(s) still exist" -Level WARNING
$issuesFound += "Services still exist: $($services.Count)"
} else {
Write-Log "✓ No Google Update services found" -Level SUCCESS
}
return $issuesFound
}
function Show-WhatIfReport {
<#
.SYNOPSIS
Display comprehensive WhatIf report
#>
Write-Host ""
Write-Host "═══════════════════════════════════════════════════════════════" -ForegroundColor Cyan
Write-Host " WhatIf Mode - Summary Report" -ForegroundColor White
Write-Host "═══════════════════════════════════════════════════════════════" -ForegroundColor Cyan
Write-Host ""
Write-Host "Chrome Installation:" -ForegroundColor Yellow
Write-Host " Version: $script:ChromeVersion" -ForegroundColor White
Write-Host " Path: $script:ChromePath" -ForegroundColor White
Write-Host ""
if ($script:ComponentsFound.Processes.Count -gt 0) {
Write-Host "Running Processes: $($script:ComponentsFound.Processes.Count)" -ForegroundColor Yellow
}
if ($script:ComponentsFound.Services.Count -gt 0) {
Write-Host "Services: $($script:ComponentsFound.Services.Count)" -ForegroundColor Yellow
foreach ($svc in $script:ComponentsFound.Services) {
Write-Host " - $($svc.Name) ($($svc.Status))" -ForegroundColor Gray
}
}
if ($script:ComponentsFound.Directories.Count -gt 0) {
Write-Host ""
Write-Host "Directories to Remove: $($script:ComponentsFound.Directories.Count)" -ForegroundColor Yellow
$totalSize = 0
foreach ($dir in $script:ComponentsFound.Directories) {
$totalSize += $dir.SizeMB
Write-Host " - $($dir.Path) ($($dir.SizeMB) MB)" -ForegroundColor Gray
}
Write-Host " Total size: $([math]::Round($totalSize, 2)) MB" -ForegroundColor White
}
if ($script:ComponentsFound.RegistryKeys.Count -gt 0) {
Write-Host ""
Write-Host "Registry Keys to Remove: $($script:ComponentsFound.RegistryKeys.Count)" -ForegroundColor Yellow
if ($IsVerboseMode) {
foreach ($key in $script:ComponentsFound.RegistryKeys) {
Write-Host " - $key" -ForegroundColor Gray
}
}
}
if ($script:ComponentsFound.ScheduledTasks.Count -gt 0) {
Write-Host ""
Write-Host "Scheduled Tasks to Remove: $($script:ComponentsFound.ScheduledTasks.Count)" -ForegroundColor Yellow
foreach ($task in $script:ComponentsFound.ScheduledTasks) {
Write-Host " - $($task.TaskName)" -ForegroundColor Gray
}
}
if ($script:ComponentsFound.Shortcuts.Count -gt 0) {
Write-Host ""
Write-Host "Shortcuts to Remove: $($script:ComponentsFound.Shortcuts.Count)" -ForegroundColor Yellow
if ($IsVerboseMode) {
foreach ($shortcut in $script:ComponentsFound.Shortcuts) {
Write-Host " - $($shortcut.Name)" -ForegroundColor Gray
}
}
}
Write-Host ""
Write-Host "═══════════════════════════════════════════════════════════════" -ForegroundColor Cyan
Write-Host " No changes were made (WhatIf mode)" -ForegroundColor Green
Write-Host "═══════════════════════════════════════════════════════════════" -ForegroundColor Cyan
Write-Host ""
}
function Show-FinalReport {
<#
.SYNOPSIS
Display final execution report
#>
param(
[Parameter(Mandatory=$false)]
[array]$VerificationIssues = @()
)
Write-Host ""
Write-Host "═══════════════════════════════════════════════════════════════" -ForegroundColor Cyan
Write-Host " Chrome Uninstall Complete" -ForegroundColor White
Write-Host "═══════════════════════════════════════════════════════════════" -ForegroundColor Cyan
Write-Host ""
if ($VerificationIssues.Count -eq 0) {
Write-Host " ✓ Chrome has been completely removed" -ForegroundColor Green
Write-Host " ✓ All components cleaned successfully" -ForegroundColor Green
} else {
Write-Host " ⚠ Chrome has been removed with warnings:" -ForegroundColor Yellow
foreach ($issue in $VerificationIssues) {
Write-Host " - $issue" -ForegroundColor Yellow
}
Write-Host ""
Write-Host " Note: Some items may require a system restart to complete removal" -ForegroundColor Yellow
}
Write-Host ""
Write-Host "═══════════════════════════════════════════════════════════════" -ForegroundColor Cyan
Write-Host ""
}
#endregion
#region Main Script
# Initialize logging
Initialize-Logging
# Set WhatIf and Verbose modes from bound parameters
$script:IsWhatIfMode = $PSBoundParameters.ContainsKey('WhatIf') -and $PSBoundParameters['WhatIf']
$script:IsVerboseMode = $PSBoundParameters.ContainsKey('Verbose') -and $PSBoundParameters['Verbose']
# Display banner
if (-not $IsSilentMode) {
Write-Host ""
Write-Host "═══════════════════════════════════════════════════════════════" -ForegroundColor Cyan
Write-Host " $script:ScriptName v$script:ScriptVersion" -ForegroundColor White
if ($IsWhatIfMode) {
Write-Host " WhatIf Mode: No changes will be made" -ForegroundColor Yellow
}
Write-Host "═══════════════════════════════════════════════════════════════" -ForegroundColor Cyan
Write-Host ""
}
Write-Log "$script:ScriptName v$script:ScriptVersion started" -Level INFO
if ($IsWhatIfMode) {
Write-Log "Running in WhatIf mode - no changes will be made" -Level WARNING
}
# Check for admin rights (skip for WhatIf mode)
if (-not $IsWhatIfMode) {
if (-not (Test-AdminRights)) {
Invoke-Elevate
} else {
Write-Log "Running with administrator privileges" -Level SUCCESS
}
} else {
if (Test-AdminRights) {
Write-Log "Running with administrator privileges" -Level VERBOSE
} else {
Write-Log "Running without administrator privileges (WhatIf mode)" -Level VERBOSE
}
}
# Detect Chrome installation
$chromeInfo = Find-ChromeInstallation
$script:ChromeDetected = $chromeInfo.Installed
$script:ChromeVersion = $chromeInfo.Version
$script:ChromePath = $chromeInfo.InstallPath
if (-not $script:ChromeDetected) {
Write-Log "Google Chrome is not installed on this system" -Level INFO
Write-Log "Nothing to uninstall" -Level SUCCESS
Write-Log "Script completed successfully" -Level SUCCESS
exit 0
}
# Scan for all Chrome components
Write-Log "Chrome installation detected" -Level SUCCESS
$componentsExist = Get-ChromeComponents
if (-not $componentsExist) {
Write-Log "No Chrome components found to remove" -Level WARNING
exit 0
}
Write-Log "Detection complete" -Level SUCCESS
# If WhatIf mode, show report and exit
if ($IsWhatIfMode) {
Show-WhatIfReport
Write-Log "WhatIf scan complete - no changes were made" -Level SUCCESS
if ($script:LogFile) {
Write-Log "Log saved to: $script:LogFile" -Level INFO
}
exit 0
}
# Execute uninstall
Write-Host ""
Write-Host "═══════════════════════════════════════════════════════════════" -ForegroundColor Cyan
Write-Host " Starting Chrome Uninstall" -ForegroundColor White
Write-Host "═══════════════════════════════════════════════════════════════" -ForegroundColor Cyan
Write-Host ""
# Uninstall Chrome
$uninstallResult = Invoke-ChromeUninstall -ChromeInfo $chromeInfo
# Perform comprehensive cleanup
Invoke-ComprehensiveCleanup
# Verify removal
$verificationIssues = Test-ChromeRemoval
# Show final report
Show-FinalReport -VerificationIssues $verificationIssues
# Log completion
if ($script:LogFile) {
Write-Log "Uninstall process complete" -Level SUCCESS
Write-Log "Log saved to: $script:LogFile" -Level INFO
$endTime = Get-Date
Write-Log "Script ended at: $endTime" -Level INFO
}
# Determine exit code
if ($verificationIssues.Count -eq 0) {
Write-Log "Exiting with code 0 (Success)" -Level SUCCESS
exit 0
} else {
Write-Log "Exiting with code 1 (Completed with warnings)" -Level WARNING
exit 1
}
#endregion
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment