Initial commit

This commit is contained in:
2026-04-24 17:41:53 +08:00
commit 7105e8b165
94 changed files with 8141 additions and 0 deletions

View File

@@ -0,0 +1,82 @@
param(
[ValidateSet('Apply','Revert')]
[string]$Mode = 'Apply',
[switch]$SkipDownload # use existing C:\Users\Admin\RemoveWindowsAi.ps1 instead of re-downloading
)
[Console]::OutputEncoding = [Text.Encoding]::UTF8
$ErrorActionPreference = 'Stop'
# 1. Must be Windows PowerShell 5.1, NOT pwsh 7+
if ($PSVersionTable.PSVersion.Major -ge 7) {
throw "This wrapper must run under Windows PowerShell 5.1 (powershell.exe), not pwsh $($PSVersionTable.PSVersion). Relaunch explicitly with powershell.exe."
}
# 2. Must have Administrator token
$isAdmin = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
if (-not $isAdmin) {
throw "Current session is NOT running as Administrator. RemoveWindowsAi.ps1 requires admin and its self-elevation (UAC RunAs) will fail over SSH. Ensure the SSH user has full admin token."
}
# 3. Fetch upstream script
$workDir = Join-Path $env:TEMP 'RemoveWindowsAI'
$scriptPath = Join-Path $workDir 'RemoveWindowsAi.ps1'
$logPath = Join-Path $workDir ("run-$Mode-$(Get-Date -Format 'yyyyMMdd-HHmmss').log")
New-Item -ItemType Directory -Force -Path $workDir | Out-Null
if (-not $SkipDownload) {
$url = 'https://raw.githubusercontent.com/zoicware/RemoveWindowsAI/main/RemoveWindowsAi.ps1'
Write-Host "[*] Downloading $url"
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
Invoke-WebRequest -Uri $url -OutFile $scriptPath -UseBasicParsing
if ((Get-Item $scriptPath).Length -lt 100KB) {
throw "Downloaded script seems too small ($((Get-Item $scriptPath).Length) bytes)"
}
# PowerShell 5.1 reads files without BOM using the system ANSI code page (CP950 on zh-TW),
# which mangles non-ASCII content. Force UTF-8 by prepending a BOM if not already present.
$bytes = [IO.File]::ReadAllBytes($scriptPath)
$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($scriptPath, $bom + $bytes)
Write-Host "[*] Added UTF-8 BOM"
}
Write-Host "[*] Saved -> $scriptPath ($((Get-Item $scriptPath).Length) bytes)"
} elseif (-not (Test-Path $scriptPath)) {
throw "-SkipDownload set but $scriptPath does not exist"
}
# 4. Build args based on mode
$psArgs = @('-NoProfile','-ExecutionPolicy','Bypass','-File', $scriptPath, '-nonInteractive', '-EnableLogging')
if ($Mode -eq 'Apply') {
$psArgs += @('-AllOptions','-backupMode')
Write-Host "[*] Mode=Apply: -AllOptions -backupMode (backup saved for later revert)"
} else {
$psArgs += @('-AllOptions','-revertMode')
Write-Host "[*] Mode=Revert: -AllOptions -revertMode (requires prior backup)"
}
# 5. Execute and tee output to log
Write-Host "[*] Executing: powershell.exe $($psArgs -join ' ')"
Write-Host "[*] Log -> $logPath"
Write-Host ('-' * 60)
$proc = Start-Process -FilePath 'powershell.exe' -ArgumentList $psArgs `
-NoNewWindow -Wait -PassThru `
-RedirectStandardOutput $logPath -RedirectStandardError "$logPath.err"
Write-Host ('-' * 60)
Get-Content $logPath -ErrorAction SilentlyContinue | Select-Object -Last 80
if (Test-Path "$logPath.err") {
$errs = Get-Content "$logPath.err"
if ($errs) {
Write-Host "--- stderr ---"
$errs
}
}
Write-Host ""
Write-Host "[=] Exit code: $($proc.ExitCode)"
Write-Host "[=] Full log: $logPath"
Write-Host "[!] A reboot is recommended after this operation."
exit $proc.ExitCode