refactor(scripts): optimize system remediation and M365 export scripts
- teams: harden Classic Teams removal, protect New Teams, and clean HKU run keys - dotnet: add bootstrapper EXE uninstall support and remove orphaned 3.1.* folders - teams: add MSIX package targeting and version parsing for vulnerable New Teams builds - m365: improve Graph SDK export speed, reuse sessions, and add null-safe handling
This commit is contained in:
1 parent
4fd95b76d6
commit
5ef82842f2
19 files changed
+1651
-1268
No files matched your search
@@ -0,0 +1,135 @@
|
||||
#Requires -RunAsAdministrator
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Removes Classic Microsoft Teams and Teams Machine-Wide Installer.
|
||||
.DESCRIPTION
|
||||
Stops Classic Teams processes, uninstalls the Machine-Wide Installer via MSI,
|
||||
removes per-user Classic Teams installations, cleans residual files/registry run keys,
|
||||
and verifies that New Teams (MSTeams) remains intact.
|
||||
#>
|
||||
|
||||
$ErrorActionPreference = "Continue"
|
||||
|
||||
Write-Host "Starting Classic Microsoft Teams cleanup..." -ForegroundColor Cyan
|
||||
|
||||
# 1. Stop ONLY Classic Teams processes (preserve New Teams)
|
||||
Get-Process -Name "Teams" -ErrorAction SilentlyContinue | Stop-Process -Force -ErrorAction SilentlyContinue
|
||||
|
||||
# Stop Update.exe processes originating specifically from Classic Teams directories
|
||||
Get-Process -Name "Update" -ErrorAction SilentlyContinue | Where-Object {
|
||||
$_.Path -like "*\Microsoft\Teams\Update.exe"
|
||||
} | Stop-Process -Force -ErrorAction SilentlyContinue
|
||||
|
||||
Start-Sleep -Seconds 3
|
||||
|
||||
# 2. Remove Teams Machine-Wide Installer from HKLM registry
|
||||
$uninstallPaths = @(
|
||||
"HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*",
|
||||
"HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*"
|
||||
)
|
||||
|
||||
$machineWideInstallers = foreach ($path in$uninstallPaths) {
|
||||
Get-ItemProperty $path -ErrorAction SilentlyContinue \vert{} Where-Object {$_.DisplayName -eq "Teams Machine-Wide Installer"
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($app in$machineWideInstallers) {
|
||||
Write-Host "Found Teams Machine-Wide Installer: $($app.DisplayName) $($app.DisplayVersion)" -ForegroundColor Yellow
|
||||
|
||||
if ($app.UninstallString -match "\{[A-Fa-f0-9\-]{36}\}") {
|
||||
$productCode =$Matches[0]
|
||||
Write-Host "Uninstalling Machine-Wide Installer via MSI product code: $productCode" -ForegroundColor Cyan
|
||||
Start-Process -FilePath "msiexec.exe" -ArgumentList "/x $productCode /qn /norestart" -Wait -NoNewWindow
|
||||
}
|
||||
elseif ($app.UninstallString) {
|
||||
Write-Host "Uninstalling via UninstallString: $($app.UninstallString)" -ForegroundColor Cyan
|
||||
if ($app.UninstallString -match "msiexec") {
|
||||
$args =$app.UninstallString -replace "msiexec.exe", "" -replace "/I", "/x"
|
||||
Start-Process -FilePath "msiexec.exe" -ArgumentList "$args /qn /norestart" -Wait -NoNewWindow
|
||||
} else {
|
||||
Start-Process -FilePath "cmd.exe" -ArgumentList "/c `"$($app.UninstallString)`" /quiet /norestart" -Wait -NoNewWindow
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# 3. Clean per-user Classic Teams installations
|
||||
$usersRoot = Join-Path$env:SystemDrive "Users"
|
||||
$userProfiles = Get-ChildItem -Path $usersRoot -Directory -ErrorAction SilentlyContinue \vert{} Where-Object {$_.Name -notin @("Public", "Default", "Default User", "All Users", "defaultuser0")
|
||||
}
|
||||
|
||||
foreach ($profile in$userProfiles) {
|
||||
$localTeamsFolder = Join-Path$profile.FullName "AppData\Local\Microsoft\Teams"
|
||||
$roamingTeamsFolder = Join-Path$profile.FullName "AppData\Roaming\Microsoft\Teams"
|
||||
$updateExe = Join-Path$localTeamsFolder "Update.exe"
|
||||
|
||||
if (Test-Path $updateExe) {
|
||||
Write-Host "Uninstalling Classic Teams for profile: $($profile.Name)" -ForegroundColor Cyan
|
||||
Start-Process -FilePath $updateExe -ArgumentList "--uninstall -s" -Wait -ErrorAction SilentlyContinue
|
||||
Start-Sleep -Seconds 2
|
||||
}
|
||||
|
||||
# Remove residual AppData folders (both Local and Roaming)
|
||||
foreach ($folder in @($localTeamsFolder,$roamingTeamsFolder)) {
|
||||
if (Test-Path $folder) {
|
||||
Write-Host "Removing directory: $folder" -ForegroundColor Yellow
|
||||
Remove-Item -Path $folder -Recurse -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# 4. Remove System-Wide ProgramData Leftovers
|
||||
$leftoverPaths = @(
|
||||
"$env:ProgramData\Microsoft\Teams",
|
||||
"$env:ProgramData\Microsoft\TeamsMachineInstaller",
|
||||
"$env:ProgramData\Microsoft\TeamsCustomData"
|
||||
)
|
||||
|
||||
foreach ($path in$leftoverPaths) {
|
||||
if (Test-Path $path) {
|
||||
Write-Host "Removing leftover ProgramData path: $path" -ForegroundColor Yellow
|
||||
Remove-Item -Path $path -Recurse -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
}
|
||||
|
||||
# 5. Clean Startup Registry Run Keys across loaded user hives
|
||||
$hkuPath = "Registry::HKEY_USERS"
|
||||
Get-ChildItem -Path $hkuPath -ErrorAction SilentlyContinue | ForEach-Object {
|
||||
$runKey = Join-Path$_.PSPath "Software\Microsoft\Windows\CurrentVersion\Run"
|
||||
if (Test-Path $runKey) {
|
||||
$val = Get-ItemProperty -Path$runKey -Name "com.squirrel.teams.teams" -ErrorAction SilentlyContinue
|
||||
if ($val) {
|
||||
Write-Host "Removing Classic Teams startup reg key from hive: $($_.PSChildName)" -ForegroundColor Yellow
|
||||
Remove-ItemProperty -Path $runKey -Name "com.squirrel.teams.teams" -ErrorAction SilentlyContinue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# 6. Confirm New Teams (MSTeams) status
|
||||
$newTeams = Get-AppxPackage -Name "MSTeams" -AllUsers -ErrorAction SilentlyContinue
|
||||
|
||||
if ($newTeams) {
|
||||
Write-Host "New Teams (MSTeams) is installed:" -ForegroundColor Green
|
||||
$newTeams | Select-Object Name, Version, PackageFullName | Format-Table -AutoSize | Out-String | Write-Host
|
||||
} else {
|
||||
Write-Host "WARNING: New Teams (MSTeams) was not detected on this device." -ForegroundColor Red
|
||||
}
|
||||
|
||||
# 7. Final Verification
|
||||
$remainingMachineWide = foreach ($path in$uninstallPaths) {
|
||||
Get-ItemProperty $path -ErrorAction SilentlyContinue \vert{} Where-Object {$_.DisplayName -eq "Teams Machine-Wide Installer"
|
||||
}
|
||||
}
|
||||
|
||||
$remainingClassicFolders = foreach ($profile in$userProfiles) {
|
||||
$localTeamsFolder = Join-Path$profile.FullName "AppData\Local\Microsoft\Teams"
|
||||
if (Test-Path $localTeamsFolder) {$localTeamsFolder }
|
||||
}
|
||||
|
||||
if ($remainingMachineWide -or$remainingClassicFolders) {
|
||||
Write-Host "Cleanup completed, but some Classic Teams remnants remain." -ForegroundColor Red
|
||||
exit 1
|
||||
} else {
|
||||
Write-Host "Classic Teams and Teams Machine-Wide Installer cleanup completed successfully." -ForegroundColor Green
|
||||
exit 0
|
||||
}
|
||||
Reference in new issue
Block a user