Initial commit
This commit is contained in:
102
scripts/powershell/remove-apps.ps1
Normal file
102
scripts/powershell/remove-apps.ps1
Normal file
@@ -0,0 +1,102 @@
|
||||
[Console]::OutputEncoding = [Text.Encoding]::UTF8
|
||||
$ErrorActionPreference = 'Continue'
|
||||
|
||||
$configPath = Join-Path $PSScriptRoot 'remove-apps-config.json'
|
||||
if (-not (Test-Path $configPath)) { throw "Config not found: $configPath" }
|
||||
$cfg = Get-Content $configPath -Raw -Encoding UTF8 | ConvertFrom-Json
|
||||
|
||||
$results = @()
|
||||
|
||||
function Record([string]$name, [string]$result, [string]$detail='') {
|
||||
$script:results += [pscustomobject]@{ Name = $name; Result = $result; Detail = $detail }
|
||||
}
|
||||
|
||||
Write-Host "===== Removing Appx packages ====="
|
||||
foreach ($name in @($cfg.RemoveAppx)) {
|
||||
$pkgs = @(Get-AppxPackage -AllUsers -Name $name -ErrorAction SilentlyContinue)
|
||||
$prov = @(Get-AppxProvisionedPackage -Online -ErrorAction SilentlyContinue | Where-Object { $_.DisplayName -eq $name })
|
||||
|
||||
if ($pkgs.Count -eq 0 -and $prov.Count -eq 0) {
|
||||
Write-Host "[=] $name : not installed"
|
||||
Record $name 'not-installed'
|
||||
continue
|
||||
}
|
||||
|
||||
foreach ($p in $pkgs) {
|
||||
try {
|
||||
Write-Host "[*] Remove-AppxPackage $($p.PackageFullName)"
|
||||
Remove-AppxPackage -AllUsers -Package $p.PackageFullName -ErrorAction Stop
|
||||
} catch {
|
||||
# 0x80073D19 = NonRemovable system package. Worth noting but often unavoidable.
|
||||
if ($_.Exception.Message -match '0x80073D19|NonRemovable') {
|
||||
Write-Host "[!] $name marked NonRemovable by Windows - skipping"
|
||||
Record $name 'nonremovable' $_.Exception.Message
|
||||
} else {
|
||||
Write-Host "[!] $name install removal failed: $($_.Exception.Message)"
|
||||
Record $name 'failed-install' $_.Exception.Message
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach ($p in $prov) {
|
||||
try {
|
||||
Remove-AppxProvisionedPackage -Online -PackageName $p.PackageName -ErrorAction Stop | Out-Null
|
||||
Write-Host "[*] Remove-AppxProvisionedPackage $($p.PackageName)"
|
||||
} catch {
|
||||
# Provisioned removal often fails silently when package was already deprovisioned by other tools.
|
||||
# Only worth logging, not flagging as a hard failure.
|
||||
}
|
||||
}
|
||||
|
||||
# Verify post-state
|
||||
$after = @(Get-AppxPackage -AllUsers -Name $name -ErrorAction SilentlyContinue)
|
||||
if ($after.Count -eq 0) {
|
||||
Record $name 'removed'
|
||||
} elseif (($results | Where-Object Name -eq $name | Select-Object -Last 1).Result -ne 'nonremovable') {
|
||||
Record $name 'still-present' "after removal attempt: $(($after | Select -Expand PackageFullName) -join ',')"
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "===== Office (M365) removal ====="
|
||||
if ($cfg.RemoveOffice) {
|
||||
$c2rClient = 'C:\Program Files\Common Files\microsoft shared\ClickToRun\OfficeClickToRun.exe'
|
||||
if (Test-Path $c2rClient) {
|
||||
Write-Host "[*] Click-to-Run detected - running silent uninstall"
|
||||
$p = Start-Process -FilePath $c2rClient -ArgumentList 'scenario=uninstall','sourcetype=None','DisplayLevel=False' -Wait -PassThru
|
||||
Write-Host "[=] OfficeClickToRun exited $($p.ExitCode)"
|
||||
} else {
|
||||
Write-Host "[=] No Click-to-Run Office present"
|
||||
}
|
||||
|
||||
$anyOfficeAppx = $false
|
||||
foreach ($pat in @('Microsoft.MicrosoftOfficeHub','Microsoft.Office.*','Microsoft.OutlookForWindows')) {
|
||||
$hit = @(Get-AppxPackage -AllUsers -Name $pat -ErrorAction SilentlyContinue)
|
||||
foreach ($p in $hit) {
|
||||
$anyOfficeAppx = $true
|
||||
try {
|
||||
Write-Host "[*] Remove-AppxPackage $($p.PackageFullName)"
|
||||
Remove-AppxPackage -AllUsers -Package $p.PackageFullName -ErrorAction Stop
|
||||
Record $p.Name 'removed'
|
||||
} catch {
|
||||
Write-Host "[!] $($p.Name) failed: $($_.Exception.Message)"
|
||||
Record $p.Name 'failed-install' $_.Exception.Message
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((-not (Test-Path $c2rClient)) -and (-not $anyOfficeAppx)) {
|
||||
Write-Host "[=] No Office / M365 traces found - nothing to do"
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "===== Summary ====="
|
||||
$byResult = $results | Group-Object Result | Sort-Object Name
|
||||
foreach ($g in $byResult) {
|
||||
Write-Host ("{0,-15}: {1}" -f $g.Name, $g.Count)
|
||||
}
|
||||
$problem = $results | Where-Object { $_.Result -in 'failed-install','still-present' }
|
||||
if ($problem) {
|
||||
Write-Host ""
|
||||
Write-Host "Needs attention:"
|
||||
$problem | ForEach-Object { Write-Host " - $($_.Name) [$($_.Result)] $($_.Detail)" }
|
||||
}
|
||||
Reference in New Issue
Block a user