<# .SYNOPSIS v3.1.3: 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 中 Bookworm 注入的内容 (skills/hooks/agents/scripts)`n" $msg += " - HKCU DPAPI 凭证缓存`n" $msg += " - PowerShell profile (PS7+PS5.1) 中的 BW_* 块`n" $msg += " - 还原截图 Toast 默认设置`n" $msg += " - ANTHROPIC_* User 环境变量`n`n" $msg += "保留:`n" $msg += " - ~/.claude/CLAUDE.md, memory/, projects/ (用户自有内容)`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 Bookworm 注入内容 (精准删除, 保留用户自有配置) ── Log "[2/7] 清 ~/.claude/ 中 Bookworm 注入的文件" $claudeDir = Join-Path $env:USERPROFILE '.claude' if (Test-Path $claudeDir) { # 只删 Bookworm 管理的子目录和文件, 不删用户自己的 CLAUDE.md / memory / projects $bwManagedDirs = @('skills', 'hooks', 'agents', 'scripts', 'constitution', 'patches', 'session-state') foreach ($d in $bwManagedDirs) { $dp = Join-Path $claudeDir $d if (Test-Path $dp) { try { Remove-Item $dp -Recurse -Force -EA Stop; Log " ✓ 删 $d/" } catch { Log " [!] 删 $d/ 失败: $_" } } } # 删 Bookworm 的配置文件 (settings.json 含 hooks 注册) foreach ($f in @('settings.json', 'settings.local.json', 'stats-compiled.json')) { $fp = Join-Path $claudeDir $f if (Test-Path $fp) { try { Remove-Item $fp -Force -EA Stop; Log " ✓ 删 $f" } catch { Log " [!] 删 $f 失败: $_" } } } Log " · 保留 ~/.claude/CLAUDE.md, memory/, projects/ (用户自有内容)" } # ── [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