param( [switch]$KeepWorkDir ) [Console]::OutputEncoding = [Text.Encoding]::UTF8 $ErrorActionPreference = 'Stop' # 1. Must be Windows PowerShell 5.1 (Win11Debloat targets powershell.exe) if ($PSVersionTable.PSVersion.Major -ge 7) { throw "Run with powershell.exe 5.1, not pwsh $($PSVersionTable.PSVersion)" } # 2. Must have Administrator token $isAdmin = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) if (-not $isAdmin) { throw "Administrator token required" } # 3. Config must exist beside this script $userConfigSrc = Join-Path $PSScriptRoot 'win11debloat-config.json' if (-not (Test-Path $userConfigSrc)) { throw "Missing $userConfigSrc" } # 4. Download repo zip to a fresh work dir $workDir = Join-Path $env:TEMP 'Win11Debloat-run' if (Test-Path $workDir) { Remove-Item $workDir -Recurse -Force } New-Item -ItemType Directory -Path $workDir | Out-Null $zipUrl = 'https://github.com/Raphire/Win11Debloat/archive/refs/heads/master.zip' $zipPath = Join-Path $workDir 'repo.zip' Write-Host "[*] Downloading $zipUrl" [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 Invoke-WebRequest -Uri $zipUrl -OutFile $zipPath -UseBasicParsing if ((Get-Item $zipPath).Length -lt 100KB) { throw "Downloaded zip seems too small" } Expand-Archive -Path $zipPath -DestinationPath $workDir -Force $repoRoot = Join-Path $workDir 'Win11Debloat-master' if (-not (Test-Path (Join-Path $repoRoot 'Win11Debloat.ps1'))) { throw "Win11Debloat.ps1 missing after extract" } # 5. Stage our config alongside the repo and BOM-patch all .ps1 files # (PowerShell 5.1 on zh-TW Windows reads non-BOM files as CP950 → breaks) $userConfigDst = Join-Path $repoRoot 'my-config.json' Copy-Item $userConfigSrc $userConfigDst -Force $psFiles = Get-ChildItem -Path $repoRoot -Recurse -Filter '*.ps1' $added = 0 foreach ($f in $psFiles) { $bytes = [IO.File]::ReadAllBytes($f.FullName) $hasBom = $bytes.Length -ge 3 -and $bytes[0] -eq 0xEF -and $bytes[1] -eq 0xBB -and $bytes[2] -eq 0xBF if (-not $hasBom) { $bom = [byte[]](0xEF, 0xBB, 0xBF) [IO.File]::WriteAllBytes($f.FullName, $bom + $bytes) $added++ } } Write-Host "[*] BOM-patched $added of $($psFiles.Count) .ps1 files" # 6. Run Win11Debloat $logPath = Join-Path $repoRoot ("run-$(Get-Date -Format 'yyyyMMdd-HHmmss').log") $script = Join-Path $repoRoot 'Win11Debloat.ps1' Write-Host "[*] Running Win11Debloat -Silent -Config my-config.json" Write-Host "[*] Log -> $logPath" Write-Host ('-' * 60) Push-Location $repoRoot try { $proc = Start-Process -FilePath 'powershell.exe' -ArgumentList @( '-NoProfile','-ExecutionPolicy','Bypass','-File', $script, '-Silent','-Config', $userConfigDst, '-LogPath', $logPath, '-NoRestartExplorer' ) -NoNewWindow -Wait -PassThru } finally { Pop-Location } Write-Host ('-' * 60) if (Test-Path $logPath) { Write-Host "--- log tail ---" Get-Content $logPath | Select-Object -Last 100 } Write-Host "" Write-Host "[=] Exit code: $($proc.ExitCode)" Write-Host "[=] Full log: $logPath" Write-Host "[!] Reboot (or at least restart Explorer) to apply UI changes." if (-not $KeepWorkDir) { Write-Host "[*] Cleaning up $workDir (use -KeepWorkDir to keep)" Remove-Item $workDir -Recurse -Force -ErrorAction SilentlyContinue } exit $proc.ExitCode