Skip to content

install.ps1 在 Windows 下一键安装失败:① 脚本带 UTF-8 BOM ② 不传 -Version 时解析出的版本号是垃圾值 #113

Description

@Alan-IFT

install.ps1 在 Windows 下一键安装失败:① 脚本带 UTF-8 BOM ② 不传 -Version 时解析出的版本号是垃圾值

环境

  • Windows / PowerShell 7.6.0-rc.1
  • pnpm 10.30.3
  • dsh-better-sidebar 目标版本 0.12.2
  • 网络:中国大陆,pnpm 的 registry 指向 https://registry.npmmirror.com(脚本内 $REGISTRY 默认写死 https://registry.npmjs.org

问题一:install.ps1 带 UTF-8 BOM,脚本自述的 irm | iex 一键安装无法使用

脚本头部注释里推荐的用法:

irm https://raw.githubusercontent.com/omdsh-dev/DSH-better-sidebar/main/scripts/install.ps1 | iex

实际执行报错:

#: The term '#' is not recognized as a name of a cmdlet, function, script file, or executable program.

param:
Line |
  39 |  param(
     |  ~~~~~
     | The term 'param' is not recognized as a name of a cmdlet, function, script file, or executable program.

原因:irm 返回的字符串开头保留了 BOM(U+FEFF),iex 把它当成命令名,导致第一行注释未被识别为注释;连锁效应是第 39 行的 param( 不再是首条语句,整个参数块失效

此时脚本仍会继续往下跑,最终拼出的命令行是:

[install] 执行 dsh plugin --profile web add dsh-better-sidebar@ False False ...
ERR_PNPM_FETCH_404  GET https://registry.npmmirror.com/False: Not Found - 404

pnpm 把 False 当成包名去装,404 失败。

改用 -OutFile 存盘后再 pwsh -File 执行,这两条解析错误消失(PowerShell 读取文件时会正确处理 BOM),说明问题确实出在 BOM 上。

建议scripts/install.ps1UTF-8 without BOM 保存并提交。同时建议在文档里把一键安装写成对 BOM 免疫的形式,例如:

& ([scriptblock]::Create(((irm '<url>') -replace '^\uFEFF','')))

问题二:不传 -Version 时,Resolve-Spec 会返回非版本号字符串

绕开 BOM 后(pwsh -File install.ps1,不带 -Version):

[install] 执行 dsh plugin --profile web add dsh-better-sidebar@npm help ...
ERR_PNPM_NO_MATCHING_VERSION  No matching version found for dsh-better-sidebar@npm

$SPEC 被解析成了 npm help。相关代码(第 65–81 行):

function Resolve-Spec {
  param([string]$Given)
  if ([string]::IsNullOrWhiteSpace($Given) -or $Given -eq 'latest') {
    $v = $null
    foreach ($tool in @('npm', 'pnpm')) {
      if (Get-Command $tool -ErrorAction SilentlyContinue) {
        $v = (& $tool view $PKG version "--registry=$REGISTRY" 2>$null | Select-Object -Last 1)
        if ($v) { break }
      }
    }
    if ($v) { return ([string]$v).Trim() }
    Warn '无法联网解析最新版本(npm/pnpm 查询失败),回退为 latest,由 pnpm 直接解析。'
    ...

核心问题:$v 只判断了非空,没有校验内容是不是版本号。当 npm view 因为网络原因失败、但仍有内容落到 stdout 时,这段垃圾值会被原样当作版本号拼进 add 命令。76–78 行准备好的「解析失败回退 latest」分支因此永远走不到 —— 而回退到 latest 本来是能装成功的。

(顺带一提:2>$null 是否在所有 npm/pnpm 失败路径上都能拦住输出,可能也值得一并确认;本机的表现是有内容漏进了 stdout。)

-Version 0.12.2 显式传入时一切正常,安装、bundle 注册、旧挂载行清理都成功:

[install] bundle 已注册:dsh.profile.bundles 包含 dsh-better-sidebar(下次启动自动挂载)
[install] 无旧手动挂载行,跳过
[install] 安装完成:dsh-better-sidebar@0.12.2

建议修复

$out = (& $tool view $PKG version "--registry=$REGISTRY" 2>$null | Select-Object -Last 1)
if ($out -and ("$out".Trim() -match '^\d+\.\d+\.\d+')) { $v = "$out".Trim(); break }

另外建议 $REGISTRY 的默认值不要写死 registry.npmjs.org,改为跟随用户已配置的 registry(例如 npm config get registry),否则在使用镜像源的环境下这一步几乎必然失败。


备注(非 bug)

dsh plugin add 过程中出现的一大批 missing peer @deepseek-ai/dsh-* / react / @xterm/xterm 警告,理解上应由 DSH 宿主在运行时提供,不需要装进 profile —— 如果确实如此,建议在 README 里加一句说明,避免使用者照着 pnpm 的 "Peer dependencies that should be installed" 提示去手动安装而装出两份 React。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions