bookworm-boot/tools/gen-launcher-bats.ps1
bookworm 8f6c53ec99 fix(v3.0.6): 启动器四连击 bug 根治 + 分发版阈值调整
真实用户报障驱动, 4 个 P0 闭环:

B1: wt.exe ';' 切 tab 误报 → -EncodedCommand Base64-UTF-16LE
B2: -d '%~dp0' 尾 \ 配 " 转义引号 → -d '%CD%' 无尾反斜杠 (cd /d 已切入)
B3: 子 pwsh 继承老 PATH 致 claude.exe not found → Base64 首行强制重载
    $env:Path = Machine + ';' + User, 找不到 claude 还附带 PATH 诊断
B4: install.ps1 [8/9] Skills>50 Hooks>10 阈值误报脱敏分发版残缺
    → Skills>=10 Hooks>=3 匹配 bookworm-portable-config.git 实际规模

新增工具 tools/gen-launcher-bats.ps1: 单一明文源 → Base64 → 两 bat 自动同步,
含字符集 + 长度 + round-trip PARSE 三重 health check, 以后改启动逻辑
只需改 $plainScript 一处.

向后兼容: DPAPI 凭证语义 round-trip 不变, 老快捷方式继续可用,
Installer banner v1.5 → v1.6, BWVersion 3.0.5 → 3.0.6.
2026-04-24 20:47:16 +08:00

161 lines
6.8 KiB
PowerShell
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Bookworm Portable 启动器 bat 生成工具 (v3.0.6)
# 用途: 从单一明文 PowerShell 脚本生成两个 bat, 避免手工同步 Base64 字符串不一致
# 用法: pwsh -NoProfile -File tools/gen-launcher-bats.ps1
# 输出: 启动Bookworm.bat + 更新并启动Bookworm.bat (覆盖写入)
$ErrorActionPreference = "Stop"
$repoRoot = Split-Path -Parent $PSScriptRoot
$launchBat = Join-Path $repoRoot "启动Bookworm.bat"
$updateBat = Join-Path $repoRoot "更新并启动Bookworm.bat"
# ─── 明文: DPAPI 加载 + PATH 重载 + claude 诊断 + 启动 ─────────
$plainScript = @'
Add-Type -AssemblyName System.Security
$env:Path = [Environment]::GetEnvironmentVariable('Path','Machine') + ';' + [Environment]::GetEnvironmentVariable('Path','User')
$r = 'HKCU:\Software\Bookworm\CachedEnv'
try {
(Get-ItemProperty $r -EA Stop).PSObject.Properties | Where-Object { $_.Name -match '^[A-Z_]+$' } | ForEach-Object {
$v = $_.Value
try {
$b = [Security.Cryptography.ProtectedData]::Unprotect([Convert]::FromBase64String($v), $null, [Security.Cryptography.DataProtectionScope]::CurrentUser)
$v = [Text.Encoding]::UTF8.GetString($b)
} catch {}
[Environment]::SetEnvironmentVariable($_.Name, $v, 'Process')
}
} catch {}
if (-not (Get-Command claude -ErrorAction SilentlyContinue)) {
Write-Host ''
Write-Host ' [!] claude 命令未找到' -ForegroundColor Red
Write-Host ''
Write-Host ' 可能原因:' -ForegroundColor Yellow
Write-Host ' 1. Claude Code 未安装 - 跑: npm i -g @anthropic-ai/claude-code' -ForegroundColor Gray
Write-Host ' 2. npm 全局路径不在 PATH - 重跑 Bookworm-Setup.exe 修复' -ForegroundColor Gray
Write-Host ''
Write-Host ' 当前 PATH 片段 (诊断用):' -ForegroundColor Gray
($env:Path -split ';') | Where-Object { $_ -match 'npm|nodejs|pwsh|Git' } | ForEach-Object { Write-Host " $_" -ForegroundColor DarkGray }
Write-Host ''
return
}
& claude --dangerously-skip-permissions
'@
# ─── Base64-UTF-16LE 编码 ─────────────────────────────────
$bytes = [System.Text.Encoding]::Unicode.GetBytes($plainScript)
$enc = [Convert]::ToBase64String($bytes)
# 健康检查
if ($enc.Length -gt 7500) { throw "Base64 长度 $($enc.Length) 超 bat 变量安全上限 7500" }
$bad = $enc -replace '[A-Za-z0-9+/=]', ''
if ($bad) { throw "Base64 含非法字符: [$bad]" }
Write-Host "[gen-launcher-bats] Base64 长度: $($enc.Length), 纯字符集检查 OK" -ForegroundColor Green
# ─── bat 1: 启动Bookworm.bat ──────────────────────────────
$launch = @"
@echo off
chcp 65001 > nul
cd /d "%~dp0"
::
set NO_PROXY=bww.letcareme.com,code.letcareme.com,letcareme.com,localhost,127.0.0.1
set no_proxy=%NO_PROXY%
:: (bookworm-boot + .claude , )
echo [..] ...
git pull --rebase >nul 2>nul
git -C "%USERPROFILE%\.claude" pull --rebase >nul 2>nul
set USE_WT=0
where wt >nul 2>nul && set USE_WT=1
set USE_PWSH7=0
where pwsh >nul 2>nul && set USE_PWSH7=1
:: v3.0.6: Base64-UTF-16LE (PATH + DPAPI + claude + )
:: A-Za-z0-9+/= , wt.exe ';' tab ( 64856bc )
:: -d "%CD%" , -d "%~dp0" ( 0c33109 )
:: : pwsh -NoProfile -File tools/gen-launcher-bats.ps1
set ENC=$enc
:: : wt + pwsh7
if %USE_WT% equ 1 if %USE_PWSH7% equ 1 (
start "" wt new-tab --title "Bookworm Smart Assistant" -d "%CD%" -- pwsh -NoLogo -NoExit -EncodedCommand %ENC%
exit
)
:: 2: wt + powershell 5.1
if %USE_WT% equ 1 if %USE_PWSH7% equ 0 (
start "" wt new-tab --title "Bookworm Smart Assistant" -d "%CD%" -- powershell -NoLogo -ExecutionPolicy Bypass -NoExit -EncodedCommand %ENC%
exit
)
:: 3: conhost + pwsh7 ( wt ; tab , Base64 )
if %USE_PWSH7% equ 1 (
start "Bookworm Smart Assistant" pwsh -NoLogo -NoExit -EncodedCommand %ENC%
exit
)
:: 4: 退 PowerShell 5.1 (, install.ps1 -StartOnly )
title Bookworm Portable
echo.
echo [!] PowerShell 7 , 使 PowerShell 5.1
echo.
powershell -ExecutionPolicy Bypass -File install.ps1 -StartOnly -AutoAccept
if %errorlevel% neq 0 (
echo.
echo 退...
pause > nul
)
"@
# ─── bat 2: 更新并启动Bookworm.bat ───────────────────────
$update = @"
@echo off
chcp 65001 > nul
cd /d "%~dp0"
::
set NO_PROXY=bww.letcareme.com,code.letcareme.com,letcareme.com,localhost,127.0.0.1
set no_proxy=%NO_PROXY%
:: (bookworm-boot + .claude )
echo [..] ...
git pull --rebase >nul 2>nul
git -C "%USERPROFILE%\.claude" pull --rebase >nul 2>nul
:: v3.0.6: Bookworm.bat Base64 (DPAPI + PATH + claude )
set ENC=$enc
:: pwsh7
where pwsh >nul 2>nul
if %errorlevel% equ 0 (
:: pwsh7: (SkipLaunch claude), -EncodedCommand
pwsh -NoLogo -ExecutionPolicy Bypass -File "%~dp0install.ps1" -AutoAccept -SkipLaunch
start "Bookworm Smart Assistant" pwsh -NoLogo -NoExit -EncodedCommand %ENC%
exit
)
:: 退 PowerShell 5.1: ++ ()
title Bookworm Portable
powershell -ExecutionPolicy Bypass -File "%~dp0install.ps1" -AutoAccept
if %errorlevel% neq 0 (
echo.
echo 退...
pause > nul
)
"@
# ─── 写入 ─────────────────────────────────────────────────
# bat 文件默认期望 GBK/ANSI, 但脚本顶部 chcp 65001 已切换到 UTF-8, 用无 BOM UTF-8 写入
[System.IO.File]::WriteAllText($launchBat, $launch, [System.Text.UTF8Encoding]::new($false))
[System.IO.File]::WriteAllText($updateBat, $update, [System.Text.UTF8Encoding]::new($false))
Write-Host "[gen-launcher-bats] ✓ 启动Bookworm.bat ($((Get-Item $launchBat).Length) bytes)" -ForegroundColor Green
Write-Host "[gen-launcher-bats] ✓ 更新并启动Bookworm.bat ($((Get-Item $updateBat).Length) bytes)" -ForegroundColor Green
# ─── Round-trip 验证 ─────────────────────────────────────
$decoded = [System.Text.Encoding]::Unicode.GetString([Convert]::FromBase64String($enc))
$err = $null
[void][System.Management.Automation.Language.Parser]::ParseInput($decoded, [ref]$null, [ref]$err)
if ($err) { throw "解码后脚本 PARSE ERR: $($err[0])" }
Write-Host "[gen-launcher-bats] ✓ Round-trip PARSE OK ($($decoded.Length) chars)" -ForegroundColor Green