Update 8x8-Cleanup-script.ps1
This commit is contained in:
1 parent
2630572cd9
commit
86ea0a945c
1 file changed
+366
-366
@@ -1,367 +1,367 @@
|
|||||||
<#
|
<#
|
||||||
.SYNOPSIS
|
.SYNOPSIS
|
||||||
Detects 8x8 Work installations with version <= 8.36.2.3, silently uninstalls them,
|
Detects 8x8 Work installations with version <= 8.36.2.3, silently uninstalls them,
|
||||||
and cleans up leftover processes, files, temp directories, and registry entries.
|
and cleans up leftover processes, files, temp directories, and registry entries.
|
||||||
|
|
||||||
.DESCRIPTION
|
.DESCRIPTION
|
||||||
1. Scans Machine (64-bit & 32-bit) and User (HKCU + loaded user hives) Uninstall registry keys for "8x8 Work".
|
1. Scans Machine (64-bit & 32-bit) and User (HKCU + loaded user hives) Uninstall registry keys for "8x8 Work".
|
||||||
2. Checks if the installed version is less than or equal to 8.36.2.3.
|
2. Checks if the installed version is less than or equal to 8.36.2.3.
|
||||||
3. Stops running 8x8 Work processes.
|
3. Stops running 8x8 Work processes.
|
||||||
4. Runs silent uninstallation (MSI /x /qn or EXE silent flags).
|
4. Runs silent uninstallation (MSI /x /qn or EXE silent flags).
|
||||||
5. Cleans up leftover folders (Program Files, ProgramData, AppData Local/Roaming, Temp) and registry entries.
|
5. Cleans up leftover folders (Program Files, ProgramData, AppData Local/Roaming, Temp) and registry entries.
|
||||||
|
|
||||||
.NOTES
|
.NOTES
|
||||||
Run as Administrator for system-wide cleanup, or in user context if only removing per-user installs.
|
Run as Administrator for system-wide cleanup, or in user context if only removing per-user installs.
|
||||||
#>
|
#>
|
||||||
|
|
||||||
[CmdletBinding(SupportsShouldProcess = $true)]
|
[CmdletBinding(SupportsShouldProcess = $true)]
|
||||||
param (
|
param (
|
||||||
[version]$MaxTargetVersion = [version]"8.36.2.3",
|
[version]$MaxTargetVersion = [version]"8.36.2.3",
|
||||||
[string]$AppNamePattern = "*8x8 Work*"
|
[string]$AppNamePattern = "*8x8 Work*"
|
||||||
)
|
)
|
||||||
|
|
||||||
$ErrorActionPreference = "Stop"
|
$ErrorActionPreference = "Stop"
|
||||||
|
|
||||||
function Write-Log {
|
function Write-Log {
|
||||||
param (
|
param (
|
||||||
[string]$Message,
|
[string]$Message,
|
||||||
[ValidateSet("INFO", "WARN", "ERROR")][string]$Level = "INFO"
|
[ValidateSet("INFO", "WARN", "ERROR")][string]$Level = "INFO"
|
||||||
)
|
)
|
||||||
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
|
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
|
||||||
Write-Output "[$timestamp] [$Level] $Message"
|
Write-Output "[$timestamp] [$Level] $Message"
|
||||||
}
|
}
|
||||||
|
|
||||||
function ConvertTo-SafeVersion {
|
function ConvertTo-SafeVersion {
|
||||||
param ([string]$VersionString)
|
param ([string]$VersionString)
|
||||||
if ([string]::IsNullOrWhiteSpace($VersionString)) { return $null }
|
if ([string]::IsNullOrWhiteSpace($VersionString)) { return $null }
|
||||||
# Extract numeric dot-separated version component (e.g. "8.36.2.3-beta" -> "8.36.2.3")
|
# Extract numeric dot-separated version component (e.g. "8.36.2.3-beta" -> "8.36.2.3")
|
||||||
if ($VersionString -match '(\d+(\.\d+){1,3})') {
|
if ($VersionString -match '(\d+(\.\d+){1,3})') {
|
||||||
try {
|
try {
|
||||||
return [version]$Matches[1]
|
return [version]$Matches[1]
|
||||||
} catch {
|
} catch {
|
||||||
return $null
|
return $null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $null
|
return $null
|
||||||
}
|
}
|
||||||
|
|
||||||
Write-Log "Starting check for 8x8 Work (Target version <= $MaxTargetVersion)..."
|
Write-Log "Starting check for 8x8 Work (Target version <= $MaxTargetVersion)..."
|
||||||
|
|
||||||
# 1. Gather Uninstall Registry Paths (System + Current User + Loaded User Hives)
|
# 1. Gather Uninstall Registry Paths (System + Current User + Loaded User Hives)
|
||||||
$UninstallPaths = @(
|
$UninstallPaths = @(
|
||||||
"HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*",
|
"HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*",
|
||||||
"HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*",
|
"HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*",
|
||||||
"HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*"
|
"HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Also check other loaded user hives in HKU when running as SYSTEM/Admin
|
# Also check other loaded user hives in HKU when running as SYSTEM/Admin
|
||||||
Get-ChildItem -Path "Registry::HKEY_USERS" -ErrorAction SilentlyContinue | Where-Object {
|
Get-ChildItem -Path "Registry::HKEY_USERS" -ErrorAction SilentlyContinue | Where-Object {
|
||||||
$_.PSChildName -match '^S-1-5-21-[\d\-]+$'
|
$_.PSChildName -match '^S-1-5-21-[\d\-]+$'
|
||||||
} | ForEach-Object {
|
} | ForEach-Object {
|
||||||
$UninstallPaths += "Registry::HKEY_USERS\$($_.PSChildName)\Software\Microsoft\Windows\CurrentVersion\Uninstall\*"
|
$UninstallPaths += "Registry::HKEY_USERS\$($_.PSChildName)\Software\Microsoft\Windows\CurrentVersion\Uninstall\*"
|
||||||
}
|
}
|
||||||
|
|
||||||
$FoundInstallations = @()
|
$FoundInstallations = @()
|
||||||
|
|
||||||
foreach ($regPath in $UninstallPaths) {
|
foreach ($regPath in $UninstallPaths) {
|
||||||
if (Test-Path $regPath) {
|
if (Test-Path $regPath) {
|
||||||
$items = Get-ItemProperty -Path $regPath -ErrorAction SilentlyContinue | Where-Object {
|
$items = Get-ItemProperty -Path $regPath -ErrorAction SilentlyContinue | Where-Object {
|
||||||
$_.DisplayName -like $AppNamePattern
|
$_.DisplayName -like $AppNamePattern
|
||||||
}
|
}
|
||||||
if ($items) {
|
if ($items) {
|
||||||
$FoundInstallations += $items
|
$FoundInstallations += $items
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Also check per-user Squirrel/Electron executable path in case registry entry is missing/corrupted
|
# Also check per-user Squirrel/Electron executable path in case registry entry is missing/corrupted
|
||||||
$UserProfileList = Get-ChildItem -Path "$env:SystemDrive\Users" -Directory -ErrorAction SilentlyContinue
|
$UserProfileList = Get-ChildItem -Path "$env:SystemDrive\Users" -Directory -ErrorAction SilentlyContinue
|
||||||
foreach ($userDir in $UserProfileList) {
|
foreach ($userDir in $UserProfileList) {
|
||||||
$possibleExePaths = @(
|
$possibleExePaths = @(
|
||||||
Join-Path $userDir.FullName "AppData\Local\8x8-work\8x8 Work.exe"
|
Join-Path $userDir.FullName "AppData\Local\8x8-work\8x8 Work.exe"
|
||||||
Join-Path $userDir.FullName "AppData\Local\Programs\8x8-work\8x8 Work.exe"
|
Join-Path $userDir.FullName "AppData\Local\Programs\8x8-work\8x8 Work.exe"
|
||||||
Join-Path $userDir.FullName "AppData\Local\8x8 Work\8x8 Work.exe"
|
Join-Path $userDir.FullName "AppData\Local\8x8 Work\8x8 Work.exe"
|
||||||
)
|
)
|
||||||
foreach ($exePath in $possibleExePaths) {
|
foreach ($exePath in $possibleExePaths) {
|
||||||
if (Test-Path $exePath) {
|
if (Test-Path $exePath) {
|
||||||
$fileVer = (Get-Item $exePath).VersionInfo.ProductVersion
|
$fileVer = (Get-Item $exePath).VersionInfo.ProductVersion
|
||||||
if (-not ($FoundInstallations | Where-Object { $_.InstallLocation -and ($exePath -like "$($_.InstallLocation)*") })) {
|
if (-not ($FoundInstallations | Where-Object { $_.InstallLocation -and ($exePath -like "$($_.InstallLocation)*") })) {
|
||||||
$FoundInstallations += [PSCustomObject]@{
|
$FoundInstallations += [PSCustomObject]@{
|
||||||
DisplayName = "8x8 Work (File Detection)"
|
DisplayName = "8x8 Work (File Detection)"
|
||||||
DisplayVersion = $fileVer
|
DisplayVersion = $fileVer
|
||||||
UninstallString = $null
|
UninstallString = $null
|
||||||
QuietUninstallString = $null
|
QuietUninstallString = $null
|
||||||
InstallLocation = Split-Path $exePath -Parent
|
InstallLocation = Split-Path $exePath -Parent
|
||||||
PSPath = $null
|
PSPath = $null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($FoundInstallations.Count -eq 0) {
|
if ($FoundInstallations.Count -eq 0) {
|
||||||
Write-Log "8x8 Work was not found on this device. Exiting."
|
Write-Log "8x8 Work was not found on this device. Exiting."
|
||||||
exit 0
|
exit 0
|
||||||
}
|
}
|
||||||
|
|
||||||
# Filter installations matching version <= 8.36.2.3
|
# Filter installations matching version <= 8.36.2.3
|
||||||
$TargetInstalls = @()
|
$TargetInstalls = @()
|
||||||
foreach ($install in $FoundInstallations) {
|
foreach ($install in $FoundInstallations) {
|
||||||
$parsedVer = ConvertTo-SafeVersion -VersionString $install.DisplayVersion
|
$parsedVer = ConvertTo-SafeVersion -VersionString $install.DisplayVersion
|
||||||
Write-Log "Found '$($install.DisplayName)' with version '$($install.DisplayVersion)' (Parsed: $parsedVer)"
|
Write-Log "Found '$($install.DisplayName)' with version '$($install.DisplayVersion)' (Parsed: $parsedVer)"
|
||||||
|
|
||||||
if ($null -ne $parsedVer -and $parsedVer -le $MaxTargetVersion) {
|
if ($null -ne $parsedVer -and $parsedVer -le $MaxTargetVersion) {
|
||||||
$TargetInstalls += $install
|
$TargetInstalls += $install
|
||||||
} elseif ($null -eq $parsedVer) {
|
} elseif ($null -eq $parsedVer) {
|
||||||
Write-Log "Could not parse version '$($install.DisplayVersion)' for $($install.DisplayName). Skipping version match." -Level "WARN"
|
Write-Log "Could not parse version '$($install.DisplayVersion)' for $($install.DisplayName). Skipping version match." -Level "WARN"
|
||||||
} else {
|
} else {
|
||||||
Write-Log "Installed version ($parsedVer) is newer than $MaxTargetVersion. Skipping uninstall."
|
Write-Log "Installed version ($parsedVer) is newer than $MaxTargetVersion. Skipping uninstall."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($TargetInstalls.Count -eq 0) {
|
if ($TargetInstalls.Count -eq 0) {
|
||||||
Write-Log "No 8x8 Work installation <= $MaxTargetVersion found. Nothing to uninstall."
|
Write-Log "No 8x8 Work installation <= $MaxTargetVersion found. Nothing to uninstall."
|
||||||
exit 0
|
exit 0
|
||||||
}
|
}
|
||||||
|
|
||||||
# 2. Stop running 8x8 Work processes before uninstalling
|
# 2. Stop running 8x8 Work processes before uninstalling
|
||||||
Write-Log "Stopping any running 8x8 Work processes..."
|
Write-Log "Stopping any running 8x8 Work processes..."
|
||||||
$ProcessNames = @("8x8 Work*", "8x8-work*", "VirtualOffice*")
|
$ProcessNames = @("8x8 Work*", "8x8-work*", "VirtualOffice*")
|
||||||
foreach ($procPattern in $ProcessNames) {
|
foreach ($procPattern in $ProcessNames) {
|
||||||
Get-Process -Name $procPattern -ErrorAction SilentlyContinue | ForEach-Object {
|
Get-Process -Name $procPattern -ErrorAction SilentlyContinue | ForEach-Object {
|
||||||
try {
|
try {
|
||||||
Write-Log "Stopping process: $($_.ProcessName) (PID: $($_.Id))"
|
Write-Log "Stopping process: $($_.ProcessName) (PID: $($_.Id))"
|
||||||
Stop-Process -Id $_.Id -Force -ErrorAction SilentlyContinue
|
Stop-Process -Id $_.Id -Force -ErrorAction SilentlyContinue
|
||||||
} catch {
|
} catch {
|
||||||
Write-Log "Failed to stop process $($_.ProcessName): $_" -Level "WARN"
|
Write-Log "Failed to stop process $($_.ProcessName): $_" -Level "WARN"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Start-Sleep -Seconds 2
|
Start-Sleep -Seconds 2
|
||||||
|
|
||||||
# 3. Uninstall matching versions silently
|
# 3. Uninstall matching versions silently
|
||||||
foreach ($app in $TargetInstalls) {
|
foreach ($app in $TargetInstalls) {
|
||||||
Write-Log "Uninstalling $($app.DisplayName) (Version: $($app.DisplayVersion))..."
|
Write-Log "Uninstalling $($app.DisplayName) (Version: $($app.DisplayVersion))..."
|
||||||
|
|
||||||
$uninstallCmd = if ($app.QuietUninstallString) { $app.QuietUninstallString } else { $app.UninstallString }
|
$uninstallCmd = if ($app.QuietUninstallString) { $app.QuietUninstallString } else { $app.UninstallString }
|
||||||
|
|
||||||
if ($app.PSChildName -match '^\{[0-9A-Fa-f\-]{36}\}$' -or $uninstallCmd -match 'msiexec') {
|
if ($app.PSChildName -match '^\{[0-9A-Fa-f\-]{36}\}$' -or $uninstallCmd -match 'msiexec') {
|
||||||
# MSI-based Uninstall
|
# MSI-based Uninstall
|
||||||
$guid = if ($app.PSChildName -match '^\{[0-9A-Fa-f\-]{36}\}$') {
|
$guid = if ($app.PSChildName -match '^\{[0-9A-Fa-f\-]{36}\}$') {
|
||||||
$app.PSChildName
|
$app.PSChildName
|
||||||
} elseif ($uninstallCmd -match '(\{[0-9A-Fa-f\-]{36}\})') {
|
} elseif ($uninstallCmd -match '(\{[0-9A-Fa-f\-]{36}\})') {
|
||||||
$Matches[1]
|
$Matches[1]
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($guid) {
|
if ($guid) {
|
||||||
$msiArgs = "/x `"$guid`" /qn /norestart REBOOT=ReallySuppress"
|
$msiArgs = "/x `"$guid`" /qn /norestart REBOOT=ReallySuppress"
|
||||||
Write-Log "Executing MSI uninstall: msiexec.exe $msiArgs"
|
Write-Log "Executing MSI uninstall: msiexec.exe $msiArgs"
|
||||||
$proc = Start-Process -FilePath "msiexec.exe" -ArgumentList $msiArgs -Wait -PassThru -NoNewWindow
|
$proc = Start-Process -FilePath "msiexec.exe" -ArgumentList $msiArgs -Wait -PassThru -NoNewWindow
|
||||||
Write-Log "MSI uninstall finished with exit code: $($proc.ExitCode)"
|
Write-Log "MSI uninstall finished with exit code: $($proc.ExitCode)"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
elseif (-not [string]::IsNullOrWhiteSpace($uninstallCmd)) {
|
elseif (-not [string]::IsNullOrWhiteSpace($uninstallCmd)) {
|
||||||
# EXE-based Uninstall (Squirrel / NSIS / InstallShield / Burn)
|
# EXE-based Uninstall (Squirrel / NSIS / InstallShield / Burn)
|
||||||
if ($uninstallCmd -match '^"([^"]+)"\s*(.*)$') {
|
if ($uninstallCmd -match '^"([^"]+)"\s*(.*)$') {
|
||||||
$exePath = $Matches[1]
|
$exePath = $Matches[1]
|
||||||
$existingArgs = $Matches[2]
|
$existingArgs = $Matches[2]
|
||||||
} else {
|
} else {
|
||||||
$parts = $uninstallCmd -split '\s+', 2
|
$parts = $uninstallCmd -split '\s+', 2
|
||||||
$exePath = $parts[0]
|
$exePath = $parts[0]
|
||||||
$existingArgs = if ($parts.Count -gt 1) { $parts[1] } else { "" }
|
$existingArgs = if ($parts.Count -gt 1) { $parts[1] } else { "" }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Test-Path $exePath) {
|
if (Test-Path $exePath) {
|
||||||
# Add appropriate silent flags if not already present
|
# Add appropriate silent flags if not already present
|
||||||
$silentArgs = $existingArgs
|
$silentArgs = $existingArgs
|
||||||
if ($exePath -like "*Update.exe*") {
|
if ($exePath -like "*Update.exe*") {
|
||||||
if ($silentArgs -notmatch '--uninstall') { $silentArgs += " --uninstall" }
|
if ($silentArgs -notmatch '--uninstall') { $silentArgs += " --uninstall" }
|
||||||
if ($silentArgs -notmatch '-s') { $silentArgs += " -s" }
|
if ($silentArgs -notmatch '-s') { $silentArgs += " -s" }
|
||||||
} else {
|
} else {
|
||||||
if ($silentArgs -notmatch '(/S|/silent|/quiet|/qn|--silent)') {
|
if ($silentArgs -notmatch '(/S|/silent|/quiet|/qn|--silent)') {
|
||||||
$silentArgs = "$silentArgs /S /quiet /norestart".Trim()
|
$silentArgs = "$silentArgs /S /quiet /norestart".Trim()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Write-Log "Executing EXE uninstall: `"$exePath`" $silentArgs"
|
Write-Log "Executing EXE uninstall: `"$exePath`" $silentArgs"
|
||||||
$proc = Start-Process -FilePath $exePath -ArgumentList $silentArgs -Wait -PassThru -NoNewWindow
|
$proc = Start-Process -FilePath $exePath -ArgumentList $silentArgs -Wait -PassThru -NoNewWindow
|
||||||
Write-Log "EXE uninstall finished with exit code: $($proc.ExitCode)"
|
Write-Log "EXE uninstall finished with exit code: $($proc.ExitCode)"
|
||||||
} else {
|
} else {
|
||||||
Write-Log "Uninstaller executable not found at: $exePath" -Level "WARN"
|
Write-Log "Uninstaller executable not found at: $exePath" -Level "WARN"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Remove the Uninstall Registry Key if it still exists
|
# Remove the Uninstall Registry Key if it still exists
|
||||||
if ($app.PSPath -and (Test-Path $app.PSPath)) {
|
if ($app.PSPath -and (Test-Path $app.PSPath)) {
|
||||||
Write-Log "Removing leftover Uninstall registry entry: $($app.PSPath)"
|
Write-Log "Removing leftover Uninstall registry entry: $($app.PSPath)"
|
||||||
Remove-Item -Path $app.PSPath -Recurse -Force -ErrorAction SilentlyContinue
|
Remove-Item -Path $app.PSPath -Recurse -Force -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Start-Sleep -Seconds 2
|
Start-Sleep -Seconds 2
|
||||||
|
|
||||||
# 4. Clean up File System Leftovers (Program Files, ProgramData, User AppData, Temp, Shortcuts)
|
# 4. Clean up File System Leftovers (Program Files, ProgramData, User AppData, Temp, Shortcuts)
|
||||||
Write-Log "Cleaning up leftover directories, caches, shortcuts, and temporary files..."
|
Write-Log "Cleaning up leftover directories, caches, shortcuts, and temporary files..."
|
||||||
|
|
||||||
$SystemFoldersToClean = @(
|
$SystemFoldersToClean = @(
|
||||||
"$env:ProgramFiles\8x8\8x8 Work",
|
"$env:ProgramFiles\8x8\8x8 Work",
|
||||||
"$env:ProgramFiles\8x8 Work",
|
"$env:ProgramFiles\8x8 Work",
|
||||||
"${env:ProgramFiles(x86)}\8x8\8x8 Work",
|
"${env:ProgramFiles(x86)}\8x8\8x8 Work",
|
||||||
"${env:ProgramFiles(x86)}\8x8 Work",
|
"${env:ProgramFiles(x86)}\8x8 Work",
|
||||||
"$env:ProgramData\8x8\8x8 Work",
|
"$env:ProgramData\8x8\8x8 Work",
|
||||||
"$env:ProgramData\8x8 Work",
|
"$env:ProgramData\8x8 Work",
|
||||||
"$env:ProgramData\8x8-work",
|
"$env:ProgramData\8x8-work",
|
||||||
"$env:ProgramData\Microsoft\Windows\Start Menu\Programs\8x8 Work*",
|
"$env:ProgramData\Microsoft\Windows\Start Menu\Programs\8x8 Work*",
|
||||||
"$env:PUBLIC\Desktop\8x8 Work*.lnk"
|
"$env:PUBLIC\Desktop\8x8 Work*.lnk"
|
||||||
)
|
)
|
||||||
|
|
||||||
foreach ($path in $SystemFoldersToClean) {
|
foreach ($path in $SystemFoldersToClean) {
|
||||||
Get-Item -Path $path -Force -ErrorAction SilentlyContinue | ForEach-Object {
|
Get-Item -Path $path -Force -ErrorAction SilentlyContinue | ForEach-Object {
|
||||||
try {
|
try {
|
||||||
Write-Log "Removing system path: $($_.FullName)"
|
Write-Log "Removing system path: $($_.FullName)"
|
||||||
Remove-Item -Path $_.FullName -Recurse -Force -ErrorAction SilentlyContinue
|
Remove-Item -Path $_.FullName -Recurse -Force -ErrorAction SilentlyContinue
|
||||||
} catch {
|
} catch {
|
||||||
Write-Log "Could not remove $($_.FullName): $_" -Level "WARN"
|
Write-Log "Could not remove $($_.FullName): $_" -Level "WARN"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Clean Windows Temp
|
# Clean Windows Temp
|
||||||
$WinTempPatterns = @(
|
$WinTempPatterns = @(
|
||||||
"$env:SystemRoot\Temp\*8x8*",
|
"$env:SystemRoot\Temp\*8x8*",
|
||||||
"$env:TEMP\*8x8*"
|
"$env:TEMP\*8x8*"
|
||||||
)
|
)
|
||||||
foreach ($pattern in $WinTempPatterns) {
|
foreach ($pattern in $WinTempPatterns) {
|
||||||
Get-Item -Path $pattern -Force -ErrorAction SilentlyContinue | ForEach-Object {
|
Get-Item -Path $pattern -Force -ErrorAction SilentlyContinue | ForEach-Object {
|
||||||
Write-Log "Removing temp item: $($_.FullName)"
|
Write-Log "Removing temp item: $($_.FullName)"
|
||||||
Remove-Item -Path $_.FullName -Recurse -Force -ErrorAction SilentlyContinue
|
Remove-Item -Path $_.FullName -Recurse -Force -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Clean Per-User Leftovers across all user profiles on the machine
|
# Clean Per-User Leftovers across all user profiles on the machine
|
||||||
foreach ($userDir in $UserProfileList) {
|
foreach ($userDir in $UserProfileList) {
|
||||||
$uPath = $userDir.FullName
|
$uPath = $userDir.FullName
|
||||||
$UserItemsToClean = @(
|
$UserItemsToClean = @(
|
||||||
"$uPath\AppData\Local\8x8\8x8 Work",
|
"$uPath\AppData\Local\8x8\8x8 Work",
|
||||||
"$uPath\AppData\Local\8x8 Work",
|
"$uPath\AppData\Local\8x8 Work",
|
||||||
"$uPath\AppData\Local\8x8-work",
|
"$uPath\AppData\Local\8x8-work",
|
||||||
"$uPath\AppData\Local\Programs\8x8-work",
|
"$uPath\AppData\Local\Programs\8x8-work",
|
||||||
"$uPath\AppData\Local\Programs\8x8 Work",
|
"$uPath\AppData\Local\Programs\8x8 Work",
|
||||||
"$uPath\AppData\Local\SquirrelTemp",
|
"$uPath\AppData\Local\SquirrelTemp",
|
||||||
"$uPath\AppData\Roaming\8x8\8x8 Work",
|
"$uPath\AppData\Roaming\8x8\8x8 Work",
|
||||||
"$uPath\AppData\Roaming\8x8 Work",
|
"$uPath\AppData\Roaming\8x8 Work",
|
||||||
"$uPath\AppData\Roaming\8x8-work",
|
"$uPath\AppData\Roaming\8x8-work",
|
||||||
"$uPath\AppData\Local\Temp\*8x8*",
|
"$uPath\AppData\Local\Temp\*8x8*",
|
||||||
"$uPath\Desktop\8x8 Work*.lnk",
|
"$uPath\Desktop\8x8 Work*.lnk",
|
||||||
"$uPath\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\8x8 Work*",
|
"$uPath\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\8x8 Work*",
|
||||||
"$uPath\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\8x8 Inc*"
|
"$uPath\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\8x8 Inc*"
|
||||||
)
|
)
|
||||||
|
|
||||||
foreach ($itemPattern in $UserItemsToClean) {
|
foreach ($itemPattern in $UserItemsToClean) {
|
||||||
Get-Item -Path $itemPattern -Force -ErrorAction SilentlyContinue | ForEach-Object {
|
Get-Item -Path $itemPattern -Force -ErrorAction SilentlyContinue | ForEach-Object {
|
||||||
# Only remove SquirrelTemp if it references 8x8 or is empty
|
# Only remove SquirrelTemp if it references 8x8 or is empty
|
||||||
if ($_.Name -eq "SquirrelTemp") {
|
if ($_.Name -eq "SquirrelTemp") {
|
||||||
$squirrelLog = Join-Path $_.FullName "SquirrelSetup.log"
|
$squirrelLog = Join-Path $_.FullName "SquirrelSetup.log"
|
||||||
if ((Test-Path $squirrelLog) -and (Select-String -Path $squirrelLog -Pattern "8x8" -Quiet -ErrorAction SilentlyContinue)) {
|
if ((Test-Path $squirrelLog) -and (Select-String -Path $squirrelLog -Pattern "8x8" -Quiet -ErrorAction SilentlyContinue)) {
|
||||||
Write-Log "Removing 8x8 SquirrelTemp folder: $($_.FullName)"
|
Write-Log "Removing 8x8 SquirrelTemp folder: $($_.FullName)"
|
||||||
Remove-Item -Path $_.FullName -Recurse -Force -ErrorAction SilentlyContinue
|
Remove-Item -Path $_.FullName -Recurse -Force -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Write-Log "Removing user path: $($_.FullName)"
|
Write-Log "Removing user path: $($_.FullName)"
|
||||||
Remove-Item -Path $_.FullName -Recurse -Force -ErrorAction SilentlyContinue
|
Remove-Item -Path $_.FullName -Recurse -Force -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Remove empty parent "8x8" directories if no other 8x8 software is inside them
|
# Remove empty parent "8x8" directories if no other 8x8 software is inside them
|
||||||
$Parent8x8Dirs = @(
|
$Parent8x8Dirs = @(
|
||||||
"$env:ProgramFiles\8x8",
|
"$env:ProgramFiles\8x8",
|
||||||
"${env:ProgramFiles(x86)}\8x8",
|
"${env:ProgramFiles(x86)}\8x8",
|
||||||
"$env:ProgramData\8x8"
|
"$env:ProgramData\8x8"
|
||||||
) + ($UserProfileList | ForEach-Object {
|
) + ($UserProfileList | ForEach-Object {
|
||||||
"$($_.FullName)\AppData\Local\8x8"
|
"$($_.FullName)\AppData\Local\8x8"
|
||||||
"$($_.FullName)\AppData\Roaming\8x8"
|
"$($_.FullName)\AppData\Roaming\8x8"
|
||||||
})
|
})
|
||||||
|
|
||||||
foreach ($parentDir in $Parent8x8Dirs) {
|
foreach ($parentDir in $Parent8x8Dirs) {
|
||||||
if (Test-Path $parentDir) {
|
if (Test-Path $parentDir) {
|
||||||
$remaining = Get-ChildItem -Path $parentDir -Force -ErrorAction SilentlyContinue
|
$remaining = Get-ChildItem -Path $parentDir -Force -ErrorAction SilentlyContinue
|
||||||
if ($null -eq $remaining -or $remaining.Count -eq 0) {
|
if ($null -eq $remaining -or $remaining.Count -eq 0) {
|
||||||
Write-Log "Removing empty parent folder: $parentDir"
|
Write-Log "Removing empty parent folder: $parentDir"
|
||||||
Remove-Item -Path $parentDir -Force -ErrorAction SilentlyContinue
|
Remove-Item -Path $parentDir -Force -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# 5. Clean up Leftover Registry Keys & Startup Entries
|
# 5. Clean up Leftover Registry Keys & Startup Entries
|
||||||
Write-Log "Cleaning up leftover registry keys and startup entries..."
|
Write-Log "Cleaning up leftover registry keys and startup entries..."
|
||||||
|
|
||||||
$RegistrySoftwarePaths = @(
|
$RegistrySoftwarePaths = @(
|
||||||
"HKLM:\SOFTWARE\8x8\8x8 Work",
|
"HKLM:\SOFTWARE\8x8\8x8 Work",
|
||||||
"HKLM:\SOFTWARE\8x8 Work",
|
"HKLM:\SOFTWARE\8x8 Work",
|
||||||
"HKLM:\SOFTWARE\WOW6432Node\8x8\8x8 Work",
|
"HKLM:\SOFTWARE\WOW6432Node\8x8\8x8 Work",
|
||||||
"HKLM:\SOFTWARE\WOW6432Node\8x8 Work",
|
"HKLM:\SOFTWARE\WOW6432Node\8x8 Work",
|
||||||
"HKCU:\SOFTWARE\8x8\8x8 Work",
|
"HKCU:\SOFTWARE\8x8\8x8 Work",
|
||||||
"HKCU:\SOFTWARE\8x8 Work"
|
"HKCU:\SOFTWARE\8x8 Work"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Include loaded user hives
|
# Include loaded user hives
|
||||||
Get-ChildItem -Path "Registry::HKEY_USERS" -ErrorAction SilentlyContinue | Where-Object {
|
Get-ChildItem -Path "Registry::HKEY_USERS" -ErrorAction SilentlyContinue | Where-Object {
|
||||||
$_.PSChildName -match '^S-1-5-21-[\d\-]+$'
|
$_.PSChildName -match '^S-1-5-21-[\d\-]+$'
|
||||||
} | ForEach-Object {
|
} | ForEach-Object {
|
||||||
$sid = $_.PSChildName
|
$sid = $_.PSChildName
|
||||||
$RegistrySoftwarePaths += @(
|
$RegistrySoftwarePaths += @(
|
||||||
"Registry::HKEY_USERS\$sid\Software\8x8\8x8 Work",
|
"Registry::HKEY_USERS\$sid\Software\8x8\8x8 Work",
|
||||||
"Registry::HKEY_USERS\$sid\Software\8x8 Work"
|
"Registry::HKEY_USERS\$sid\Software\8x8 Work"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($regKey in $RegistrySoftwarePaths) {
|
foreach ($regKey in $RegistrySoftwarePaths) {
|
||||||
if (Test-Path $regKey) {
|
if (Test-Path $regKey) {
|
||||||
Write-Log "Removing registry key: $regKey"
|
Write-Log "Removing registry key: $regKey"
|
||||||
Remove-Item -Path $regKey -Recurse -Force -ErrorAction SilentlyContinue
|
Remove-Item -Path $regKey -Recurse -Force -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Clean Windows Installer Product/Upgrade Codes in HKCR\Installer\Products if orphaned
|
# Clean Windows Installer Product/Upgrade Codes in HKCR\Installer\Products if orphaned
|
||||||
$InstallerProductsPath = "Registry::HKEY_CLASSES_ROOT\Installer\Products"
|
$InstallerProductsPath = "Registry::HKEY_CLASSES_ROOT\Installer\Products"
|
||||||
if (Test-Path $InstallerProductsPath) {
|
if (Test-Path $InstallerProductsPath) {
|
||||||
Get-ChildItem -Path $InstallerProductsPath -ErrorAction SilentlyContinue | ForEach-Object {
|
Get-ChildItem -Path $InstallerProductsPath -ErrorAction SilentlyContinue | ForEach-Object {
|
||||||
$prodName = (Get-ItemProperty -Path $_.PSPath -Name "ProductName" -ErrorAction SilentlyContinue).ProductName
|
$prodName = (Get-ItemProperty -Path $_.PSPath -Name "ProductName" -ErrorAction SilentlyContinue).ProductName
|
||||||
if ($prodName -like $AppNamePattern) {
|
if ($prodName -like $AppNamePattern) {
|
||||||
Write-Log "Removing orphaned Windows Installer product registration: $($_.PSPath) ($prodName)"
|
Write-Log "Removing orphaned Windows Installer product registration: $($_.PSPath) ($prodName)"
|
||||||
Remove-Item -Path $_.PSPath -Recurse -Force -ErrorAction SilentlyContinue
|
Remove-Item -Path $_.PSPath -Recurse -Force -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Clean Run / Startup registry values referencing 8x8 Work
|
# Clean Run / Startup registry values referencing 8x8 Work
|
||||||
$RunKeys = @(
|
$RunKeys = @(
|
||||||
"HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run",
|
"HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run",
|
||||||
"HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Run",
|
"HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Run",
|
||||||
"HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run"
|
"HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run"
|
||||||
)
|
)
|
||||||
Get-ChildItem -Path "Registry::HKEY_USERS" -ErrorAction SilentlyContinue | Where-Object {
|
Get-ChildItem -Path "Registry::HKEY_USERS" -ErrorAction SilentlyContinue | Where-Object {
|
||||||
$_.PSChildName -match '^S-1-5-21-[\d\-]+$'
|
$_.PSChildName -match '^S-1-5-21-[\d\-]+$'
|
||||||
} | ForEach-Object {
|
} | ForEach-Object {
|
||||||
$RunKeys += "Registry::HKEY_USERS\$($_.PSChildName)\Software\Microsoft\Windows\CurrentVersion\Run"
|
$RunKeys += "Registry::HKEY_USERS\$($_.PSChildName)\Software\Microsoft\Windows\CurrentVersion\Run"
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($runKey in $RunKeys) {
|
foreach ($runKey in $RunKeys) {
|
||||||
if (Test-Path $runKey) {
|
if (Test-Path $runKey) {
|
||||||
$props = Get-ItemProperty -Path $runKey -ErrorAction SilentlyContinue
|
$props = Get-ItemProperty -Path $runKey -ErrorAction SilentlyContinue
|
||||||
if ($props) {
|
if ($props) {
|
||||||
$props.PSObject.Properties | Where-Object {
|
$props.PSObject.Properties | Where-Object {
|
||||||
$_.Name -notIn @("PSPath", "PSParentPath", "PSChildName", "PSDrive", "PSProvider") -and
|
$_.Name -notIn @("PSPath", "PSParentPath", "PSChildName", "PSDrive", "PSProvider") -and
|
||||||
($_.Name -like "*8x8*" -or $_.Value -like "*8x8*")
|
($_.Name -like "*8x8*" -or $_.Value -like "*8x8*")
|
||||||
} | ForEach-Object {
|
} | ForEach-Object {
|
||||||
Write-Log "Removing startup Run value '$($_.Name)' from $runKey"
|
Write-Log "Removing startup Run value '$($_.Name)' from $runKey"
|
||||||
Remove-ItemProperty -Path $runKey -Name $_.Name -Force -ErrorAction SilentlyContinue
|
Remove-ItemProperty -Path $runKey -Name $_.Name -Force -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Write-Log "8x8 Work uninstallation and cleanup completed successfully."
|
Write-Log "8x8 Work uninstallation and cleanup completed successfully."
|
||||||
exit 0
|
exit 0
|
||||||
Reference in new issue
Block a user