mcpField
S
setup-local-sdk

setup-local-sdk

github.com/dotnet开发5.8k3.1k 次安装1 天前更新
代码仓库

关于 setup-local-sdk

指导开发者将 .NET SDK 安装到项目本地的 `.dotnet/`,并配置 `global.json` 选择该 SDK,不改动系统级安装,同时说明验证与清理步骤。

主要功能

  1. 01项目本地 SDK 安装
  2. 02配置 `global.json` paths
  3. 03检查宿主版本前提
  4. 04按平台提供安装步骤
  5. 05按需安装 workloads
  6. 06生成团队安装脚本

适用场景

  1. 01为单个项目隔离 SDK
  2. 02配置预览版或指定版本 SDK
  3. 03准备可复用的团队或 CI 配置
  4. 04删除本地 SDK 以撤销设置

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/dotnet/skills --skill setup-local-sdk

安装后在 Claude Code 中输入/setup-local-sdk确认已加载。

详细介绍

setup-local-sdk

用途

指导用户将 .NET SDK 安装到项目本地的 .dotnet/ 目录,并通过 global.json 的 paths 功能(.NET 10+)进行配置。 示例使用 .NET 11,但此方法适用于任何版本,无论是预发行版还是稳定版。

最终得到的是完全隔离的 SDK,它:

  • 不会修改系统范围的 .NET 安装。
  • 从项目根目录运行 dotnet 命令时会自动使用。
  • 可以删除以恢复原状(rm -rf .dotnet/ 或 Remove-Item -Recurse -Force .\.dotnet)。

不适用场景

  • 用户需要系统范围安装——请引导其使用官方安装程序。
  • 主机上的 dotnet 版本低于 v10——不存在 paths 功能;请说明并停止。
  • 用户只需要安装运行时——paths 仅适用于 SDK 解析。

输入 / 前提条件

输入必需默认值备注
通道或版本否11.0例如:11.0、STS、LTS,或类似 11.0.100-preview.2.26159.112 的确切版本
质量否preview可选值:daily、preview、ga
jq否—使用 bash 团队脚本修补现有 global.json 时可选;如果没有 jq,请勿覆盖该文件
前提条件
  1. 已全局安装 .NET 10+ SDK——运行 dotnet --version;主版本号需 ≥ 10。
  2. 可使用 curl(macOS/Linux)或 PowerShell(Windows)。

工作流

步骤 1 — 确认要安装的版本

如果用户未指定,请询问其需要哪个 .NET SDK 版本(例如“最新的 .NET 11 预览版”或类似 11.0.100-preview.2.26159.112 的确切版本)。 将回答映射为 --channel/--quality 或 --version 标志。

步骤 2 — 验证 .NET 10+ 主机

如果用户已提供 dotnet --version 的输出,请将其视为该用户机器上版本的权威信息。不要用 Agent 工作区中的版本覆盖;如果两者不同,请说明工作区中的版本不同,并继续针对用户的机器提供指导。

dotnet --version

如果主版本号 < 10,请在下载任何内容之前停止:paths 功能需要 .NET 10+ 主机 SDK。告知用户先在系统范围内安装 .NET 10 或更高版本,然后再继续设置本地 SDK。

步骤 3 — 检测操作系统

运行 uname -s 2>/dev/null。如果成功(包括 MINGW*、MSYS*、CYGWIN*——这些都是支持 bash 的环境,例如 Git Bash),则使用 bash/dotnet-install.sh。 如果失败(未安装 Git Bash 的原生 Windows 环境),则使用 PowerShell/dotnet-install.ps1。

步骤 4 — 检查是否已有本地 SDK

macOS / Linux:

test -d .dotnet && echo "exists" || echo "not found"

Windows(PowerShell):

if (Test-Path -LiteralPath .\.dotnet) { "exists" } else { "not found" }

如果 .dotnet/ 已存在,请询问:要更新到新版本,还是跳过并保留现有版本?

步骤 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

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>(bash)或 -Version <VERSION>(PowerShell),而不是通道/质量标志。安装脚本来自 Microsoft 官方 URL:https://dot.net/v1/dotnet-install.sh 和 https://dot.net/v1/dotnet-install.ps1。

步骤 6 — 确认已安装的版本
./.dotnet/dotnet --version          # macOS/Linux
.\.dotnet\dotnet.exe --version      # Windows

记录确切的版本字符串(例如 11.0.100-preview.2.26159.112),以便写入 global.json。

步骤 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$ 作为系统级回退。
  • rollForward: "latestFeature":用于安装最新预览版或浮动功能带版本。
  • 精确版本请求:使用 rollForward: "disable",以免 SDK 解析切换到其他功能带。
  • allowPrerelease:仅在安装预发布版 SDK 时设为 true。稳定版本请省略。
  • errorMessage:仅在创建团队安装脚本时添加(步骤 10)。否则请省略。

如果 global.json 已存在,请谨慎合并:保留现有属性(如 msbuild-sdks、 tools 等),只添加或更新 sdk 部分。先读取现有文件,更新或添加 大模型 对象,然后写回文件。这样可以确保不会丢失跨项目配置(例如 MSBuild 设置)。 修改前务必备份原始文件(例如 global.json.bak)。

最简配置(无需固定版本时): {"sdk":{"paths":[".dotnet","$host$"]}}

步骤 8 — 更新 .gitignore

macOS / Linux(或 Git Bash):

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/'
}
步骤 9 — 安装工作负载(如有要求)

仅在完成 global.json 和 .gitignore 后执行此操作,避免耗时较长或受平台限制的 工作负载安装影响基础本地 SDK 配置的可用性。

如果用户提到了 MAUI、移动端、工作负载、Blazor WASM 或跨平台, 请使用本地二进制文件安装(无需 sudo):

./.dotnet/dotnet workload install <workload>       # macOS/Linux
.\.dotnet\dotnet.exe workload install <workload>   # Windows

验证:./.dotnet/dotnet workload list(或 .\.dotnet\dotnet.exe workload list)。

对于 MAUI,请选择当前操作系统和目标平台支持的工作负载。在 Linux 上,无法使用完整的 maui 元工作负载;如果目标是 Android,请使用受支持的工作负载 (例如 maui-android),或说明平台限制并询问要配置哪个目标平台。

始终使用本地 dotnet 二进制文件执行工作负载命令。 工作负载元数据 存储在相对于宿主进程 dotnet 根目录的位置。系统 dotnet 会将 元数据放在错误的位置。(请参阅 dotnet/sdk#49825。)

步骤 10 — 创建团队安装脚本

如果用户提到“团队”“共享”“CI”“脚本”等内容,则创建脚本。否则请主动提出。 这些示例会备份 global.json 并保留现有设置。bash 脚本 会在需要修改现有 global.json 时使用 jq;如果没有 jq, 则会拒绝覆盖文件,并输出需要手动合并的设置。 根据步骤 1 中选择的安装方式调整脚本变量:精确版本应使用 --version / -Version 和 rollForward: "disable";通道安装应使用通道/质量设置,并且仅对预发布版 SDK 设置 allowPrerelease: true。 如果 global.json 已固定 sdk.version,且用户主要需要团队 脚本,请在脚本中沿用该版本,并先更新 global.json;不要为了确认版本而 开始漫长的 SDK 下载。如果用户同时要求配置和脚本,请在任何耗时较长的安装之前创建脚本/配置,以确保即使下载或工作负载安装缓慢,也已有可复现的配置。

install-dotnet.sh:

#!/usr/bin/env bash
set -euo pipefail
INSTALL_DIR=".dotnet"
CHANNEL="11.0"
QUALITY="preview"
VERSION=""
ROLL_FORWARD="latestFeature"
ALLOW_PRERELEASE="true"
WORKLOADS=("${@}")
ERROR_MESSAGE="Required .NET SDK not found. Run ./install-dotnet.sh (or .ps1) to install it locally."
INSTALL_SCRIPT="$(mktemp "${TMPDIR:-/tmp}/dotnet-install.XXXXXX")"
GLOBAL_JSON_TMP=""
cleanup() {
    rm -f "$INSTALL_SCRIPT"
    [ -n "$GLOBAL_JSON_TMP" ] && rm -f "$GLOBAL_JSON_TMP"
}
trap cleanup EXIT
curl -fsSL https://dot.net/v1/dotnet-install.sh -o "$INSTALL_SCRIPT"
INSTALL_ARGS=(--install-dir "$INSTALL_DIR")
if [ -n "$VERSION" ]; then
    INSTALL_ARGS+=(--version "$VERSION")
    ROLL_FORWARD="disable"
else
    INSTALL_ARGS+=(--channel "$CHANNEL" --quality "$QUALITY")
fi
bash "$INSTALL_SCRIPT" "${INSTALL_ARGS[@]}"
SDK_VERSION=$("$INSTALL_DIR/dotnet" --version)
write_global_json() {
    if [ -f global.json ]; then
        cp global.json global.json.bak
        if ! command -v jq >/dev/null 2>&1; then
            echo "global.json exists; install succeeded, but this script will not overwrite it without jq." >&2
            echo "Merge these sdk settings manually so existing global.json properties are preserved:" >&2
            cat >&2 <<EOF
{
  "sdk": {
    "version": "$SDK_VERSION",
    "allowPrerelease": $ALLOW_PRERELEASE,
    "rollForward": "$ROLL_FORWARD",
    "paths": [".dotnet", "\$host\$"],
    "errorMessage": "$ERROR_MESSAGE"
  }
}
EOF
            exit 1
        fi
        GLOBAL_JSON_TMP="$(mktemp "${TMPDIR:-/tmp}/global-json.XXXXXX")"
        jq --arg version "$SDK_VERSION" --arg rollForward "$ROLL_FORWARD" --argjson allowPrerelease "$ALLOW_PRERELEASE" --arg errorMessage "$ERROR_MESSAGE" '
          .sdk = ((.sdk // {}) + {
            version: $version,
            allowPrerelease: $allowPrerelease,
            rollForward: $rollForward,
            paths: [".dotnet", "$host$"],
            errorMessage: $errorMessage
          })
        ' global.json > "$GLOBAL_JSON_TMP"
        mv "$GLOBAL_JSON_TMP" global.json
        GLOBAL_JSON_TMP=""
    else
        cat > global.json <<EOF
{
  "sdk": {
    "version": "$SDK_VERSION",
    "allowPrerelease": $ALLOW_PRERELEASE,
    "rollForward": "$ROLL_FORWARD",
    "paths": [".dotnet", "\$host\$"],
    "errorMessage": "$ERROR_MESSAGE"
  }
}
EOF
    fi
}
write_global_json
grep -qxF '.dotnet/' .gitignore 2>/dev/null || printf '\n.dotnet/\n' >> .gitignore
[ ${#WORKLOADS[@]} -gt 0 ] && "$INSTALL_DIR/dotnet" workload install "${WORKLOADS[@]}"
echo "Done. SDK: $SDK_VERSION"
chmod +x install-dotnet.sh

install-dotnet.ps1:

param([string[]]$Workloads = @())
$ErrorActionPreference = 'Stop'
$installDir = '.dotnet'; $channel = '11.0'; $quality = 'preview'
$version = ''; $rollForward = 'latestFeature'; $allowPrerelease = $true
$errorMessage = 'Required .NET SDK not found. Run ./install-dotnet.sh (or .ps1) to install it locally.'
$installScript = Join-Path $env:TEMP "dotnet-install-$([guid]::NewGuid()).ps1"
try {
    Invoke-WebRequest -Uri 'https://dot.net/v1/dotnet-install.ps1' -OutFile $installScript
    $installArgs = @('-InstallDir', $installDir)
    if ($version) {
        $installArgs += @('-Version', $version)
        $rollForward = 'disable'
    } else {
        $installArgs += @('-Channel', $channel, '-Quality', $quality)
    }
    & $installScript @installArgs
}
finally {
    if (Test-Path -LiteralPath $installScript) {
        Remove-Item -LiteralPath $installScript -Force
    }
}
$sdkVersion = & "$installDir\dotnet.exe" --version
$globalJson = if (Test-Path 'global.json') {
    Copy-Item 'global.json' 'global.json.bak'
    Get-Content -Path 'global.json' -Raw | ConvertFrom-Json
} else {
    [pscustomobject]@{}
}
if (-not $globalJson.PSObject.Properties['sdk']) {
    $globalJson | Add-Member -MemberType NoteProperty -Name 'sdk' -Value ([pscustomobject]@{})
}
$updates = [ordered]@{
    version = $sdkVersion
    allowPrerelease = $allowPrerelease
    rollForward = $rollForward
    paths = @('.dotnet', '$host$')
    errorMessage = $errorMessage
}
foreach ($entry in $updates.GetEnumerator()) {
    $property = $globalJson.sdk.PSObject.Properties[$entry.Key]
    if ($property) {
        $property.Value = $entry.Value
    } else {
        $globalJson.sdk | Add-Member -MemberType NoteProperty -Name $entry.Key -Value $entry.Value
    }
}
$globalJson | ConvertTo-Json -Depth 10 | Set-Content -Path 'global.json' -Encoding UTF8
if (-not (Test-Path .gitignore) -or -not (Select-String -Path .gitignore -Pattern '^\.dotnet/$' -Quiet)) {
    Add-Content -Path .gitignore -Value '.dotnet/'
}
if ($Workloads.Count -gt 0) { & "$installDir\dotnet.exe" workload install @Workloads }
Write-Host "Done. SDK: $sdkVersion"

将这些脚本提交到代码库,以便团队成员运行。

步骤 11 — 验证 SDK 解析
dotnet --version

输出应与本地安装的版本一致。如果不一致,请检查:global.json 的位置、paths 数组的内容、宿主 dotnet 版本是否 ≥ 10。

步骤 12 — 总结并说明清理方式

告诉用户:SDK 已安装,global.json 已配置,.dotnet/ 已加入 gitignore,未更改系统安装。清理方式:删除 .dotnet/,从 global.json 中移除 paths/errorMessage,也可以选择删除安装脚本。附上最终的 global.json sdk 值(或简短代码片段),以便用户查看已配置的版本、paths 和任何 errorMessage。如果用户要求安装工作负载,请附上所用的本地 dotnet workload install ... 命令,以及工作负载验证结果;如果无法安装工作负载,则说明具体阻碍。

常见问题

问题原因解决方法
忽略了 paths主机上的 dotnet < v10在系统范围内安装 .NET 10+
解析到错误的 SDK父目录中存在 global.json检查上层目录中的 global.json
队友遇到“找不到 SDK”.dotnet/ 已加入 gitignore,且未运行安装脚本在 global.json 中使用 errorMessage
缺少工作负载使用了系统的 dotnet,而非本地版本使用 ./.dotnet/dotnet workload install
dotnet app.dll 使用了错误的运行时paths 仅适用于 SDK,不适用于 apphost使用 dotnet run 或设置 DOTNET_ROOT

评论

支持 Markdown