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