From 3cb6f1dac103c689cca72ff052093ef84569029e Mon Sep 17 00:00:00 2001 From: bookworm Date: Tue, 7 Apr 2026 18:28:12 +0800 Subject: [PATCH] =?UTF-8?q?fix(installer):=20=E4=BF=AE=E5=A4=8D=20EXE=20?= =?UTF-8?q?=E5=AE=89=E8=A3=85=E5=99=A8=E5=85=B3=E9=94=AE=E7=BC=BA=E9=99=B7?= =?UTF-8?q?=20+=20=E5=A4=9A=E7=94=A8=E6=88=B7=E5=8A=A0=E5=AF=86=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E9=A6=96=E5=8F=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 根因 (auto-setup.ps1): 1. $BootUrl 定义但未使用 — bookworm-boot 仓库从未被克隆 2. $ScriptDir 在 PS2EXE 打包后回退到 $PWD (Downloads 目录) 3. Phase 4 在 EXE 同目录找 crypto-helper.js / secrets-*.enc → 必然失败 4. Phase 6 桌面快捷方式同样指向 $ScriptDir → 路径错误 修复: - $ScriptDir 改用 Process.MainModule + PSScriptRoot 三级回退 (PS2EXE 兼容) - 新增 $BootDir = $ScriptDir/bookworm-boot - Phase 3 增加克隆/更新 bookworm-boot 仓库逻辑 (失败 fail-fast) - Phase 4 crypto-helper.js / secrets-*.enc 路径统一指向 $BootDir - Phase 6 快捷方式 .bat 路径同样改用 $BootDir 附加: - 新增多用户加密文件 secrets-dfff6f13.enc (用户: 茶师兄, 30 天有效期) - .gitignore 新增 users.txt / .tmp-authcodes.json / auto-setup.ps1.bak-* 防泄露 - 删除旧版 secrets.enc (单用户共享模式废弃) 测试: - gen-authcode.js → encrypt → crypto-helper.js decrypt 闭环验证通过 - PS2EXE build artifact (215 KB) 经字符串扫描确认 5 处补丁已编译 Co-Authored-By: Claude Opus 4.6 (1M context) --- .gitignore | 3 +++ auto-setup.ps1 | 58 ++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 50 insertions(+), 11 deletions(-) diff --git a/.gitignore b/.gitignore index 4ce37a3..a0b8260 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ secrets.txt +users.txt +auto-setup.ps1.bak-* +.tmp-authcodes.json 管理员SOP.html dist/ diff --git a/auto-setup.ps1 b/auto-setup.ps1 index b4759cf..9837de3 100644 --- a/auto-setup.ps1 +++ b/auto-setup.ps1 @@ -16,12 +16,22 @@ param( $ErrorActionPreference = "Stop" # ─── 路径定义 ──────────────────────────────────────── -$ScriptDir = if ($MyInvocation.MyCommand.Path) { Split-Path -Parent $MyInvocation.MyCommand.Path } else { $PWD.Path } +# PS2EXE 兼容: $MyInvocation.MyCommand.Path 在 EXE 启动时为空,需用 Process MainModule +$ScriptDir = if ($PSScriptRoot) { + $PSScriptRoot +} elseif ([System.Diagnostics.Process]::GetCurrentProcess().MainModule.FileName -match '\.exe$') { + Split-Path -Parent ([System.Diagnostics.Process]::GetCurrentProcess().MainModule.FileName) +} elseif ($MyInvocation.MyCommand.Path) { + Split-Path -Parent $MyInvocation.MyCommand.Path +} else { + $PWD.Path +} $ClaudeDir = Join-Path $env:USERPROFILE ".claude" $BackupDir = Join-Path $env:USERPROFILE ".claude.bw-backup" $GitUrl = "https://code.letcareme.com/bookworm/bookworm-config.git" $BootUrl = "https://code.letcareme.com/bookworm/bookworm-boot.git" -$SecretsEnc = Join-Path $ScriptDir "secrets.enc" +$BootDir = Join-Path $ScriptDir "bookworm-boot" +$SecretsEnc = Join-Path $BootDir "secrets.enc" $TOTAL_PHASES = 7 # ─── GUI 初始化 ───────────────────────────────────── @@ -238,21 +248,21 @@ function New-DesktopShortcuts { $shell = New-Object -ComObject WScript.Shell $desktop = $shell.SpecialFolders("Desktop") - # 快速启动 + # 快速启动 (bat 文件位于 bookworm-boot 仓库内) $shortcut = $shell.CreateShortcut("$desktop\Bookworm.lnk") - $batPath = Join-Path $ScriptDir "启动Bookworm.bat" - if (-not (Test-Path $batPath)) { $batPath = Join-Path $ScriptDir "Bookworm-OneClick.bat" } + $batPath = Join-Path $BootDir "启动Bookworm.bat" + if (-not (Test-Path $batPath)) { $batPath = Join-Path $BootDir "Bookworm-OneClick.bat" } $shortcut.TargetPath = $batPath - $shortcut.WorkingDirectory = $ScriptDir + $shortcut.WorkingDirectory = $BootDir $shortcut.Description = "Bookworm Smart Assistant" $shortcut.Save() # 更新启动 $shortcut2 = $shell.CreateShortcut("$desktop\更新Bookworm.lnk") - $updateBat = Join-Path $ScriptDir "更新并启动Bookworm.bat" + $updateBat = Join-Path $BootDir "更新并启动Bookworm.bat" if (Test-Path $updateBat) { $shortcut2.TargetPath = $updateBat - $shortcut2.WorkingDirectory = $ScriptDir + $shortcut2.WorkingDirectory = $BootDir $shortcut2.Description = "更新并启动 Bookworm" $shortcut2.Save() } @@ -592,6 +602,32 @@ foreach ($d in $dirs) { if (-not (Test-Path $p)) { New-Item -ItemType Directory -Path $p -Force | Out-Null } } +# ─── 克隆/更新 bookworm-boot (含 crypto-helper.js + secrets-*.enc + install.ps1) ─── +if (Test-Path (Join-Path $BootDir ".git")) { + Log-Info "boot 仓库已存在, 更新中..." + Push-Location $BootDir + try { + git pull --rebase 2>&1 | ForEach-Object { Write-Host " $_" -ForegroundColor Gray } + Log-OK "boot 仓库已更新" + } catch { Log-Warn "boot 仓库更新失败, 使用本地版本" } + finally { Pop-Location } +} else { + Log-Info "克隆 boot 仓库 (含解密工具与凭证)..." + if (-not $cred) { $cred = Show-GiteaCredentialDialog } + if ($cred) { + $bootCredUrl = $BootUrl -replace '://', "://$($cred.User):$($cred.Pass)@" + git clone --depth 1 $bootCredUrl $BootDir 2>&1 | ForEach-Object { Write-Host " $_" -ForegroundColor Gray } + } else { + git clone --depth 1 $BootUrl $BootDir 2>&1 | ForEach-Object { Write-Host " $_" -ForegroundColor Gray } + } + if (-not (Test-Path (Join-Path $BootDir "crypto-helper.js"))) { + Log-Fail "boot 仓库克隆失败 (crypto-helper.js 缺失)" + Show-MsgBox "boot 仓库克隆失败。`n请检查网络和 Gitea 凭证。" "克隆失败" "OK" "Error" + exit 1 + } + Log-OK "boot 仓库克隆成功 → $BootDir" +} + # ======================================================================== # Phase 4: 凭证解密 (GUI 弹窗) # ======================================================================== @@ -606,12 +642,12 @@ if (Get-CachedSecrets) { } # 再解密 (缓存命中则跳过) if (-not $secretsDecrypted) { -$cryptoHelper = Join-Path $ScriptDir "crypto-helper.js" +$cryptoHelper = Join-Path $BootDir "crypto-helper.js" $useNode = (Test-Cmd "node") -and (Test-Path $cryptoHelper) if (-not $useNode -and -not $opensslCmd) { Log-Fail "无解密工具 (需要 Node.js 或 OpenSSL)" } -elseif ((Test-Path $SecretsEnc) -or (Get-ChildItem $ScriptDir -Filter "secrets-*.enc" -ErrorAction SilentlyContinue)) { +elseif ((Test-Path $SecretsEnc) -or (Get-ChildItem $BootDir -Filter "secrets-*.enc" -ErrorAction SilentlyContinue)) { $validAttempts = 0 while ($validAttempts -lt 3) { $rawCode = Show-AuthCodeDialog ($validAttempts + 1) 3 @@ -633,7 +669,7 @@ elseif ((Test-Path $SecretsEnc) -or (Get-ChildItem $ScriptDir -Filter "secrets-* # 按 token 前8位定位 .enc 文件 (多用户独立 Key),回退 secrets.enc $fileId = $token.Substring(0, 8) - $encFile = Join-Path $ScriptDir "secrets-$fileId.enc" + $encFile = Join-Path $BootDir "secrets-$fileId.enc" if (-not (Test-Path $encFile)) { $encFile = $SecretsEnc } if (-not (Test-Path $encFile)) { Show-MsgBox "未找到对应凭证文件。`n请确认管理员已推送 secrets-$fileId.enc 到 Gitea`n并重新运行安装器(会自动拉取)。" "文件未找到" "OK" "Warning"