diff --git a/auto-setup.ps1 b/auto-setup.ps1 index 7fdf48f..4d55d9d 100644 --- a/auto-setup.ps1 +++ b/auto-setup.ps1 @@ -19,8 +19,36 @@ param( $ErrorActionPreference = "Stop" +# ─── v3.0.7: 顶层 trap 防静默闪退 ─────────────────── +# 场景: PS2EXE 包装的 .exe 在 ErrorActionPreference=Stop 模式下, 任何未处理 +# cmdlet/方法异常直接结束进程. 无 trap 则用户看到"安装到一半窗口消失", +# 无错误信息可报障. 此 trap 把异常写崩溃日志 + 弹 GUI 让用户截图. +$global:BWCrashLog = Join-Path $env:TEMP "bw-crash.log" +trap { + $e = $_ + $msg = "[$([DateTime]::Now.ToString('s'))] UNHANDLED EXCEPTION`n" + $msg += "Message : $($e.Exception.Message)`n" + $msg += "Type : $($e.Exception.GetType().FullName)`n" + $msg += "Location : $($e.InvocationInfo.ScriptName):$($e.InvocationInfo.ScriptLineNumber):$($e.InvocationInfo.OffsetInLine)`n" + $msg += "Line : $($e.InvocationInfo.Line.Trim())`n" + $msg += "Stack:`n$($e.ScriptStackTrace)`n" + $msg += "---`n" + try { $msg | Out-File -FilePath $global:BWCrashLog -Append -Encoding UTF8 -EA SilentlyContinue } catch {} + # 尝试弹 GUI (Add-Type 可能失败, try 包裹) + try { + Add-Type -AssemblyName System.Windows.Forms -EA Stop + $shortMsg = "Bookworm 安装遇到未处理异常, 进程将退出.`n`n" + $shortMsg += "错误: $($e.Exception.Message)`n" + $shortMsg += "位置: $(Split-Path $e.InvocationInfo.ScriptName -Leaf):$($e.InvocationInfo.ScriptLineNumber)`n`n" + $shortMsg += "详细日志已写入:`n $global:BWCrashLog`n`n" + $shortMsg += "请把该日志文件截图发给管理员报障." + [System.Windows.Forms.MessageBox]::Show($shortMsg, "Bookworm 安装异常 v$BWVersion", 'OK', 'Error') | Out-Null + } catch {} + exit 2 +} + # ─── 版本号 (每次更新递增, build.ps1 自动读取) ────── -$BWVersion = "3.0.6" # fix: 启动器 bat 修复 wt ';' 切 tab + -d 转义引号 + PATH 重载 + claude 诊断 + 阈值调整 +$BWVersion = "3.0.7" # hotfix: 顶层 trap 防闪退 + Phase 5.5 regex 字面替换 + 可选步骤 try-catch 降级 # DryRun 模式日志标记 if ($DryRun) { $global:BWDryRun = $DryRun } else { $global:BWDryRun = $null } @@ -1775,6 +1803,9 @@ $env:CLAUDE_HOME = $ClaudeDir Log-Info "[5.5/$TOTAL_PHASES] 截图粘贴助手部署" Update-Progress-SubStatus "配置截图粘贴助手..." +# v3.0.7: 整段 Phase 5.5 包 try-catch, 任何失败都降级到 Log-Warn 不阻断主流程 +# 原因: Phase 5.5 是可选体验增强, 失败不应导致主安装流程闪退 (Phase 6/7 还没跑) +try { $clipWatcherSrc = Join-Path $ClaudeDir "scripts\ClipImageWatcher.ps1" if (Test-Path $clipWatcherSrc) { # ── 5.5a: profile sentinel 注入 (幂等, 精准替换 BW_CLIP_START..END 中间块) ── @@ -1848,12 +1879,15 @@ $sentinelEnd "@ # 读现有 profile, 精准替换 sentinel 中间块 (不动其他内容) + # v3.0.7 修复: 原 -replace 运算符把 replacement 里的 $script:/`$HOME/$1 等当作 backreference, + # 导致生成的 profile.ps1 损坏. 改用 [regex]::Match + String.Replace 字面替换绕过 $ 语义. $existing = if (Test-Path $psProfilePath) { Get-Content $psProfilePath -Raw -Encoding UTF8 } else { "" } $pattern = [regex]::Escape($sentinelStart) + "[\s\S]*?" + [regex]::Escape($sentinelEnd) - if ($existing -match $pattern) { - $updated = [regex]::Replace($existing, $pattern, [regex]::Escape($bwClipBlock) -replace '\\(.)', '$1', 1) - # 上面 Regex.Replace 的 replacement 参数需要 escape 一次, 改用简单字符串替换 - $updated = $existing -replace $pattern, [System.Text.RegularExpressions.Regex]::Unescape([regex]::Escape($bwClipBlock)) + $regex = [regex]::new($pattern) + $match = $regex.Match($existing) + if ($match.Success) { + # 字面替换: 把匹配到的旧块整段 String.Replace 成新块, 不走正则 replacement 语义 + $updated = $existing.Replace($match.Value, $bwClipBlock) } else { $updated = if ($existing) { $existing.TrimEnd() + "`n`n" + $bwClipBlock + "`n" } else { $bwClipBlock + "`n" } } @@ -1889,6 +1923,11 @@ $sentinelEnd } else { Log-Warn "ClipImageWatcher.ps1 未分发到 $clipWatcherSrc, 跳过截图助手部署" } +} catch { + # v3.0.7: 截图助手是可选功能, 失败降级不阻断主流程 + Log-Warn "Phase 5.5 截图助手部署异常 (不影响主功能): $($_.Exception.Message)" + try { "[$([DateTime]::Now.ToString('s'))] PHASE_5_5_FAIL $($_.Exception.Message) @ $($_.InvocationInfo.ScriptLineNumber)" | Out-File -FilePath $global:BWCrashLog -Append -Encoding UTF8 -EA SilentlyContinue } catch {} +} # ======================================================================== # Phase 6: MCP 验证 + 自动安装