后端与接口
需要安全试用 .NET 预览版、固定特定 SDK…
在项目根目录把指定 .NET SDK(含预览版)安装到 .dotnet/,通过 global.json 的 paths 让 dotnet 命令优先使用本地 SDK,不改系统安装。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 38/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 59/100 ×0.15
适用场景
需要安全试用 .NET 预览版、固定特定特定
解决思路
- 准备输入:Channel 或 version 可选,默认 `11.0`,可传 `11.0`、`STS`、`LTS` 或精确版本如 `11.0.100-preview.2.26159.112`;Quality 可选,默认 `preview`,取值为 `daily`、`preview`、`ga`;bash 团队脚本在 patch 现有 global.json 时可选依赖 `jq`,没有 `jq` 时不要覆盖该文件。
- 前置检查:全局已安装 .NET 10+ SDK,运行 `dotnet --version`,主版本 ≥ 10。
- 前置检查:macOS/Linux 有 `curl`,Windows 有 PowerShell。
- Step 1 明确安装内容:如果用户未指定,询问要安装哪个 .NET SDK 版本(例如 latest .NET 11 preview 或精确版本 `11.0.100-preview.2.26159.112`),并把答案映射到 `--channel`/`--quality` 或 `--version` 参数。
- Step 2 验证 .NET 10+ host:如果用户已提供 `dotnet --version` 输出,以用户机器的输出为准,不要用 agent workspace 的版本覆盖;如果两者不同,说明 workspace 不同并继续按用户机器建议。运行 `dotnet --version`;若主版本 < 10,停止下载,告诉用户先系统安装 .NET 10 或更高版本再回来。
- Step 3 检测操作系统:运行 `uname -s 2>/dev/null`。成功(包括 `MINGW*`、`MSYS*`、`CYGWIN*` 这类支持 bash 的环境,如 Git Bash)→ 使用 bash/`dotnet-install.sh`;失败(无 Git Bash 的原生 Windows)→ 使用 PowerShell/`dotnet-install.ps1`。
- Step 4 检查现有本地 SDK:macOS/Linux 运行 `test -d .dotnet && echo "exists" || echo "not found"`;Windows PowerShell 运行 `if (Test-Path -LiteralPath ./.dotnet) { "exists" } else { "not found" }`。如果 `.dotnet/` 存在,询问用户要用新版本更新,还是跳过并保留。
- Step 5 下载并运行安装脚本(macOS/Linux): INSTALL_SCRIPT="$(mktemp "${TMPDIR:-/tmp}/dotnet-install.XXXXXX")" trap 'rm -f "$INSTALL_SCRIPT"' EXIT curl -fsSL https://dot.net/v1/dotnet-install.sh -o "$INSTALL_SCRIPT" bash "$INSTALL_SCRIPT" --channel <CHANNEL> --quality <QUALITY> --install-dir .dotnet 精确版本时改用 `--version <VERSION>` 替代 channel/quality。
- Step 5 下载并运行安装脚本(Windows PowerShell): $installScript = Join-Path $env:TEMP "dotnet-install-$([guid]::NewGuid()).ps1" try { Invoke-WebRequest -Uri 'https://dot.net/v1/dotnet-install.ps1' -OutFile $installScript & $installScript -Channel <CHANNEL> -Quality <QUALITY> -InstallDir .dotnet } finally { if (Test-Path -LiteralPath $installScript) { Remove-Item -LiteralPath $installScript -Force } } 精确版本时改用 `-Version <VERSION>` 替代 channel/quality。安装脚本来自官方 URL:`https://dot.net/v1/dotnet-install.sh` 和 `https://dot.net/v1/dotnet-install.ps1`。
- Step 6 识别已安装版本:macOS/Linux 运行 `./.dotnet/dotnet --version`,Windows 运行 `.dotnet/dotnet.exe --version`,记录精确版本字符串(例如 `11.0.100-preview.2.26159.112`)供 `global.json` 使用。
- Step 7 创建或更新 `global.json`:示例 `{"sdk":{"version":"<INSTALLED_VERSION>","allowPrerelease":true,"rollForward":"latestFeature","paths":[".dotnet","$host$"],"errorMessage":"Required .NET SDK not found. Run ./install-dotnet.sh (or .ps1) to install it locally."}}`。`paths` 中 `.dotnet` 优先,`$host$` 为系统级回退。
- Step 7 配置规则:`rollForward: "latestFeature"` 用于 latest-preview 或 floating feature-band 安装;精确版本请求使用 `rollForward: "disable"`,避免 SDK 解析移动到不同 feature band;`allowPrerelease` 仅在安装预览版 SDK 时设为 `true`,稳定版省略;`errorMessage` 仅在创建团队安装脚本时包含,否则省略。
- Step 7 合并现有 `global.json`:如果已存在,先备份原文件为 `global.json.bak`,读取现有文件,保留已有属性(如 `msbuild-sdks`、`tools` 等),只添加/更新 `sdk` 对象,再写回,避免丢失跨项目配置。
- Step 7 最小配置:不需要固定版本时使用 `{"sdk":{"paths":[".dotnet","$host$"]}}`。
- Step 8 更新 `.gitignore`:macOS/Linux 运行 `grep -qxF '.dotnet/' .gitignore 2>/dev/null || printf '\n.dotnet/\n' >> .gitignore`;Windows PowerShell 运行 `if (-not (Test-Path .gitignore) -or -not (Select-String -Path .gitignore -Pattern '^.dotnet/$' -Quiet)) { Add-Content -Path .gitignore -Value '.dotnet/' }`。
- Step 9 安装 workloads(仅当请求时):在 `global.json` 和 `.gitignore` 完成后执行,避免慢或平台受限的 workload 安装影响基础本地 SDK 可用性。如果用户提到 MAUI、mobile、workload、Blazor WASM 或 cross-platform,使用本地 binary 安装(无需 sudo):macOS/Linux `./.dotnet/dotnet workload install <workload>`,Windows `.dotnet/dotnet.exe workload install <workload>`。
- Step 9 验证和平台限制:运行 `./.dotnet/dotnet workload list`(或 `.dotnet/dotnet.exe workload list`)验证;MAUI 要选择当前 OS 和目标平台支持的 workload;Linux 上完整 `maui` meta-workload 不可用,Android 目标可用 `maui-android`,或解释平台限制并询问要配置哪个目标。
- Step 9 关键规则:workload 命令始终使用本地 dotnet binary。workload metadata 相对于 host 进程的 dotnet root 存储,系统 `dotnet` 会把 metadata 放到错误位置(见 dotnet/sdk#49825)。
- Step 10 创建团队安装脚本:如果用户提到 team、share、CI、scripts 等就创建,否则 offer。脚本应备份 `global.json` 并保留现有设置;bash 脚本在需要 patch 现有 `global.json` 时使用 `jq`,没有 `jq` 时拒绝覆盖并打印需要手动合并的 sdk 设置。
- Step 10 根据安装选择适配脚本:精确版本用 `--version`/`-Version` 且设置 `rollForward: "disable"`;channel 安装用 channel/quality,且仅在 prerelease SDK 时设置 `allowPrerelease: true`。
- Step 10 复用已有版本:如果 `global.json` 已固定 `sdk.version` 且用户主要需要团队脚本,复用该版本并先更新 `global.json`;不要只为发现版本而启动长 SDK 下载。用户同时要 setup 和 scripts 时,在任何长安装前先创建 scripts/config,使可复现设置即使下载或 workload 安装很慢也存在。
- Step 10 创建 `install-dotnet.sh`:脚本逻辑包括 `set -euo pipefail`;定义 `INSTALL_DIR=".dotnet"`、`CHANNEL="11.0"`、`QUALITY="preview"`、`VERSION=""`、`ROLL_FORWARD="latestFeature"`、`ALLOW_PRERELEASE="true"`、`WORKLOADS=("${@}")`、`ERROR_MESSAGE=...`;用 `mktemp` 下载官方脚本并 `trap cleanup EXIT`;如果 `VERSION` 非空则给安装参数加 `--version "$VERSION"` 并设 `ROLL_FORWARD="disable"`,否则加 `--channel "$CHANNEL" --quality "$QUALITY"`;安装后执行 `SDK_VERSION=$("$INSTALL_DIR/dotnet" --version)`;若 `global.json` 存在则 `cp global.json global.json.bak`,无 `jq` 时拒绝覆盖并打印 sdk 设置,有 `jq` 时用 jq 将 `.sdk = ((.sdk // {}) + {version, allowPrerelease, rollForward, paths: [".dotnet", "$host$"], errorMessage})` 合并到临时文件后 `mv` 回去;若不存在则用 heredoc 创建 `global.json`;追加 `.dotnet/` 到 `.gitignore`;若有 workloads 则执行 `"$INSTALL_DIR/dotnet" workload install "${WORKLOADS[@]}"`;最后输出 `Done. SDK: $SDK_VERSION`。
- Step 10 创建 `install-dotnet.ps1`:脚本逻辑包括 `param([string[]]$Workloads = @())`、`$ErrorActionPreference = 'Stop'`;定义 `$installDir = '.dotnet'`、`$channel = '11.0'`、`$quality = 'preview'`、`$version = ''`、`$rollForward = 'latestFeature'`、`$allowPrerelease = $true`、`$errorMessage = ...`;用临时脚本路径并 try/finally 下载和运行 `dotnet-install.ps1`;如果 `$version` 非空则加 `-Version` 并设 `$rollForward = 'disable'`,否则加 `-Channel`/`-Quality`;安装后获取 `$sdkVersion = & "$installDir\dotnet.exe" --version`;若 `global.json` 存在则 `Copy-Item 'global.json' 'global.json.bak'` 并用 `ConvertFrom-Json` 读取,否则创建空对象;确保 `sdk` 属性存在后,用 ordered 哈希更新 `version`、`allowPrerelease`、`rollForward`、`paths = @('.dotnet', '$host$')`、`errorMessage`;用 `ConvertTo-Json -Depth 10 | Set-Content -Path 'global.json' -Encoding UTF8` 写回;追加 `.dotnet/` 到 `.gitignore`;若 `$Workloads.Count -gt 0` 则执行 `& "$installDir\dotnet.exe" workload install @Workloads`;最后 `Write-Host "Done. SDK: $sdkVersion"`。
- Step 10 完成脚本后:运行 `chmod +x install-dotnet.sh`,并把安装脚本提交到 repo 让队友可运行。
- Step 11 验证 SDK 解析:运行 `dotnet --version`,输出应匹配本地安装版本。若不匹配,检查 `global.json` 位置、`paths` 数组内容、host dotnet 版本是否 ≥ 10。
- Step 12 总结并解释清理:告诉用户 SDK 已安装、`global.json` 已配置、`.dotnet/` 已 gitignore、系统安装未改。清理时删除 `.dotnet/`,从 `global.json` 移除 `paths`/`errorMessage`,可选删除安装脚本。包含最终 `global.json` 的 `sdk` 值(或短片段)让用户看到配置的 version、`paths` 和 `errorMessage`。如果请求了 workloads,包含使用的本地 `dotnet workload install ...` 命令和验证结果,或无法安装的确切阻塞原因。
- 常见排错:`paths` 被忽略 → host `dotnet` < v10,系统安装 .NET 10+;解析到错误 SDK → 父目录有 `global.json`,检查树上层;队友报 SDK not found → `.dotnet/` 被 gitignore 且未运行安装脚本,在 `global.json` 使用 `errorMessage`;workloads 缺失 → 用了系统 `dotnet` 而非本地,使用 `./.dotnet/dotnet workload install`;`dotnet app.dll` 用错 runtime → `paths` 仅用于 SDK 解析,不是 apphost,使用 `dotnet run` 或设置 `DOTNET_ROOT`。
适用边界 · 注意事项
- 用户要系统级安装,应使用官方安装器。
- host `dotnet` 低于 v10,`paths` 不存在;解释并停止。
- 用户需要 runtime-only 安装,或项目不使用 SDK-style 命令;`paths` 仅适用于 SDK 解析。