bookworm-boot/卸载Bookworm-impl.ps1
bookworm ec490c3f35 feat(v3.1.2): 完整生命周期 (闭合 L9-L12)
新增:
- 卸载Bookworm.bat + 卸载Bookworm-impl.ps1: 7 步清理
- bw-doctor.ps1: 13 维度健康体检工具
- 桌面快捷方式 2→4 (新增体检+卸载)

增强:
- bw-launch.ps1: nvm/fnm/volta 探测 + log rotation
- auto-setup.ps1: npm/uvx 国内镜像双 fallback

12/12 局限全部闭合, v3.1.x 生命周期完整.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-26 15:12:15 +08:00

146 lines
6.0 KiB
PowerShell

<#
.SYNOPSIS
v3.1.2: Bookworm 完整卸载实现脚本
.DESCRIPTION
由 卸载Bookworm.bat 调用. 集中所有 PS 清理逻辑, 避免 cmd 多行 PS 转义.
清理项:
[1] 桌面 4-5 个 .lnk (启动/更新/体检/卸载/旧 Bookworm.lnk)
[2] ~/.claude/ 整个目录 (skills/hooks/agents/凭证)
[3] HKCU:\Software\Bookworm (DPAPI 缓存 + Toast 备份)
[4] PS7 + PS5.1 双 profile.ps1 的 BW_CRED + BW_CLIP 块
[5] HKCU 截图 Toast 设置还原 (从备份)
[6] ANTHROPIC_* + BW_LICENSE_KEY User 环境变量
[7] 提示用户手动删 bookworm-boot 目录
保留 (公共依赖, 不主动卸):
- Node.js / Git / PowerShell 7 / Claude Code (npm i -g)
#>
$ErrorActionPreference = "Continue"
Add-Type -AssemblyName System.Windows.Forms -EA SilentlyContinue
# ── 二次确认 ──
$msg = "确定要卸载 Bookworm 吗?`n`n"
$msg += "将删除:`n"
$msg += " - 桌面 4-5 个快捷方式`n"
$msg += " - ~/.claude 配置目录 (skills/hooks/agents)`n"
$msg += " - HKCU DPAPI 凭证缓存`n"
$msg += " - PowerShell profile (PS7+PS5.1) 中的 BW_* 块`n"
$msg += " - 还原截图 Toast 默认设置`n"
$msg += " - ANTHROPIC_* User 环境变量`n`n"
$msg += "保留 (公共依赖, 不主动卸):`n"
$msg += " - Node.js / Git / PowerShell 7 / Claude Code"
$confirm = [System.Windows.Forms.MessageBox]::Show($msg, 'Bookworm 卸载二次确认', 'YesNo', 'Warning')
if ($confirm -ne 'Yes') {
Write-Host "Bookworm 卸载已取消" -ForegroundColor Yellow
exit 0
}
$logLines = @()
function Log { param([string]$m); Write-Host $m -ForegroundColor Cyan; $script:logLines += $m }
# ── [1/7] 桌面 .lnk ──
Log "[1/7] 删桌面快捷方式"
$desk = [Environment]::GetFolderPath('Desktop')
foreach ($n in @('启动Bookworm.lnk','更新Bookworm.lnk','体检Bookworm.lnk','卸载Bookworm.lnk','Bookworm.lnk')) {
$p = Join-Path $desk $n
if (Test-Path $p) {
try { Remove-Item $p -Force -EA Stop; Log " ✓ 删 $n" }
catch { Log " [!] 删 $n 失败: $_" }
}
}
# ── [2/7] ~/.claude 目录 ──
Log "[2/7] 删 ~/.claude/ (配置 + 凭证 + skills/hooks/agents)"
$claudeDir = Join-Path $env:USERPROFILE '.claude'
if (Test-Path $claudeDir) {
try { Remove-Item $claudeDir -Recurse -Force -EA Stop; Log " ✓ 已删 $claudeDir" }
catch { Log " [!] 删除失败 (可能 claude 进程占用): $_" }
}
# ── [3/7] HKCU DPAPI 凭证 + Toast 备份元数据 ──
Log "[3/7] 清 HKCU:\Software\Bookworm DPAPI 凭证"
# 先读 Toast 备份, 后面 [5] 用
$toastOrig = $null
$bak = 'HKCU:\Software\Bookworm\ToastBackup'
if (Test-Path $bak) {
try { $toastOrig = (Get-ItemProperty -Path $bak -Name 'ScreenSketchToast_Original' -EA SilentlyContinue).ScreenSketchToast_Original } catch {}
}
foreach ($r in @('HKCU:\Software\Bookworm\CachedEnv','HKCU:\Software\Bookworm\ToastBackup','HKCU:\Software\Bookworm')) {
if (Test-Path $r) {
try { Remove-Item $r -Recurse -Force -EA Stop; Log " ✓ 删 $r" }
catch { Log " [!] 删 $r 失败: $_" }
}
}
# ── [4/7] profile.ps1 BW_CRED + BW_CLIP 块清理 (PS7+PS5.1) ──
Log "[4/7] 清 profile.ps1 BW_CRED + BW_CLIP 块"
foreach ($pdir in @(
(Join-Path $env:USERPROFILE 'Documents\PowerShell'),
(Join-Path $env:USERPROFILE 'Documents\WindowsPowerShell')
)) {
$pp = Join-Path $pdir 'profile.ps1'
if (-not (Test-Path $pp)) { continue }
try {
$c = Get-Content $pp -Raw -Encoding UTF8
$orig = $c.Length
# 兼容 v3.0.x / v3.1.x 所有 sentinel 版本
$c = [regex]::Replace($c, '# BW_CRED_START[\s\S]*?# BW_CRED_END\r?\n?', '')
$c = [regex]::Replace($c, '# BW_CLIP_START[\s\S]*?# BW_CLIP_END\r?\n?', '')
if ($c.Length -ne $orig) {
[System.IO.File]::WriteAllText($pp, $c, [System.Text.UTF8Encoding]::new($false))
Log " ✓ 清理 $pp (移除 $($orig - $c.Length) 字节)"
} else {
Log " · $pp 无 BW_* 块, 跳过"
}
} catch { Log " [!] $pp 处理失败: $_" }
}
# ── [5/7] 还原截图 Toast ──
Log "[5/7] 还原截图 Toast 设置"
$toastReg = 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Notifications\Settings\Microsoft.ScreenSketch_8wekyb3d8bbwe!App'
if ($toastOrig -eq '__ABSENT__') {
if (Test-Path $toastReg) {
try { Remove-ItemProperty -Path $toastReg -Name 'Enabled' -EA Stop; Log " ✓ Toast Enabled 项已删除 (恢复默认)" }
catch { Log " [!] Toast 还原失败: $_" }
}
} elseif ($toastOrig) {
try {
if (-not (Test-Path $toastReg)) { New-Item -Path $toastReg -Force | Out-Null }
Set-ItemProperty -Path $toastReg -Name 'Enabled' -Value ([int]$toastOrig) -Type DWord -Force
Log " ✓ Toast Enabled 还原为 $toastOrig"
} catch { Log " [!] Toast 还原失败: $_" }
} else {
Log " · 无 Toast 备份记录, 跳过"
}
# ── [6/7] ANTHROPIC_* User env ──
Log "[6/7] 清 ANTHROPIC_* / BW_LICENSE_KEY User 环境变量"
foreach ($ev in @('ANTHROPIC_API_KEY','ANTHROPIC_BASE_URL','ANTHROPIC_MODEL','BW_LICENSE_KEY')) {
$v = [Environment]::GetEnvironmentVariable($ev, 'User')
if ($v) {
try { [Environment]::SetEnvironmentVariable($ev, $null, 'User'); Log " ✓ 清 $ev" }
catch { Log " [!] 清 $ev 失败: $_" }
}
}
# ── [7/7] 提示手动删 bookworm-boot ──
Log "[7/7] 手动收尾"
Log " 请手动删除 bookworm-boot 目录 (本脚本无法删除自身所在目录):"
Log " 例如: $env:USERPROFILE\Downloads\bookworm-boot"
# ── 完成弹窗 ──
$endMsg = "Bookworm 卸载完成.`n`n"
$endMsg += "执行摘要:`n"
$endMsg += ($logLines -join "`n")
$endMsg += "`n`n保留的公共依赖 (如不再需要可手动卸):`n"
$endMsg += " - Node.js: %ProgramFiles%\nodejs`n"
$endMsg += " - Git for Windows: %ProgramFiles%\Git`n"
$endMsg += " - PowerShell 7: %ProgramFiles%\PowerShell\7`n"
$endMsg += " - Claude Code: 命令行运行 npm uninstall -g @anthropic-ai/claude-code"
[System.Windows.Forms.MessageBox]::Show($endMsg, 'Bookworm 卸载完成', 'OK', 'Information') | Out-Null
exit 0