PowerShell Windows 构建指南:.NET SDK 环境准备、Start-PSBuild 编译流程与产物定位
本篇基于仓库文档 Windows 构建指南,完整讲解在 Windows 上从源码构建 PowerShell 的全流程:如何准备 Git、Visual Studio 与 .NET CLI 环境,如何通过仓库根目录的 build.psm1 构建模块执行 Start-PSBuild 完成编译,以及如何定位并运行构建产物 pwsh.exe、用 Start-PSPester 跑通跨平台 Pester 测试。读完后你可以独立从零完成一次 Windows 下的 PowerShell 源码构建、验证产物并运行测试套件。
环境准备
原始文档说明这些步骤在 Windows 10 和 Windows Server 2012 R2 上经过验证,理论上任何依赖项可正常运行的环境都适用。构建前需要满足以下几项准备:
Git 配置
使用 Git 前需确保其配置正确,可参考仓库 README 与 贡献指南。构建指南默认你已递归克隆 PowerShell 仓库并 cd 进入仓库根目录(git clone --recursive),因为构建过程中需要子模块参与编译。
Visual Studio
安装 Visual Studio 2019(Community 社区版即可免费使用)。仓库要求至少 Visual Studio 2019 16.7 版本。
Visual Studio Code
用 VS Code 构建 PowerShell 的前提是可执行文件名为 pwsh,即系统中需已安装 PowerShell 6 Beta.9(或更高版本),通常这一依赖服务于调试目的。
.NET CLI
构建统一使用 .NET 命令行工具(dotnet)。所需 SDK 的确切版本记录在仓库根目录 global.json 中(文档中指向该文件第 3 行),当前仓库内容为:
{
"sdk": {
"version": "11.0.100-preview.6.26359.118"
}
}
构建模块会自动安装该版本并加入 PATH。两种方式任选其一:
Import-Module ./build.psm1
Start-PSBootstrap -Scenario Dotnet
或直接调用 Install-Dotnet:
Install-Dotnet
Install-Dotnet 会移除之前安装的 .NET CLI 版本,再安装 PowerShell 所依赖的版本。从 build.psm1 的 Install-Dotnet 实现可以看到,它在 Windows 分支会先删除 ~\AppData\Local\Microsoft\dotnet 目录,再下载并执行 dotnet-install.ps1,安装参数中的 Version 默认取自 global.json 中解析出的 $dotnetCLIRequiredVersion(模块加载时通过 Get-Content $PSScriptRoot/global.json | ConvertFrom-Json 读取),并附带 -skipnonversionedfiles 参数,保证与仓库声明的 SDK 版本严格一致。如果 dotnet 安装遇到问题,应查阅微软官方文档排查。
使用构建模块 Start-PSBuild 构建
仓库维护了一个 PowerShell 构建模块 build.psm1,其中 Start-PSBuild 函数负责整个编译过程。文档明确不推荐使用 Visual Studio 开发者终端(Dev Environment Terminal)来构建源码,应以该模块为入口。基本构建命令为:
Import-Module ./build.psm1
Start-PSBuild -Clean -PSModuleRestore -UseNuGetOrg
各参数的含义(结合 Start-PSBuild 的注释与实现补充):
-Clean:构建前执行git clean -fdX清理未跟踪和忽略的文件。实现中对.vs/PowerShell/v16/Server/sqlite3、src/Modules/nuget.config和根目录nuget.config做了排除,因为 Roslyn 依赖前者、发布构建依赖后两者;-PSModuleRestore:属于旧参数集,等价于默认行为——构建后把 PowerShell Gallery 模块(PowerShellGet、PackageManagement、Microsoft.PowerShell.Archive 等)恢复到输出目录;如需跳过可使用默认的-NoPSModuleRestore参数集;-UseNuGetOrg:切换为公共 NuGet.org 源。PowerShell 项目默认引用私有 Azure Artifacts 源,该源需要身份验证;加上此标志后,Switch-PSNugetConfig -Source Public会在仓库根目录、src/Modules和test/tools/Modules三处重新生成 nuget.config,指向nuget.org与 dotnet 公共源,免去认证步骤。
构建流程内部发生了什么
从 Start-PSBuild 源码看,一次完整构建依次执行:
- 前置检查:
Find-Dotnet将 .NET CLI 加入 PATH,precheck校验git与dotnet均在 PATH 中,随后Find-RequiredSDK比对已安装 SDK 版本与global.json要求;若版本不符,函数会打印已安装/所需版本及三步修复指引(删除$env:LOCALAPPDATA\Microsoft\dotnet下旧版本、重跑Start-PSBootstrap或Install-Dotnet、再执行Start-PSBuild -Clean)后直接返回; - 解析构建选项:
New-PSOptions计算顶层项目目录、RID、框架与输出路径。未显式指定-Runtime时,它会从dotnet --info解析当前平台与架构,Windows x64 会得到win7-x64、ARM64 得到win-arm64;顶层项目目录对 Windows 系 RID 固定为src/powershell-win-core; - NuGet 还原:
Restore-PSPackage对顶层项目、src/TypeCatalogGen、src/ResGen、src/Modules、tools/wix五个目录执行dotnet restore,每个项目带最多 5 次重试;Windows 系 RID 会追加/property:EnableWindowsTargeting=True与/property:UseRidGraph=True; - 代码生成:按需执行
Start-ResGen(为 resx 资源文件生成 C# 绑定)与Start-TypeGen(生成CorePsTypeCatalog.cs,按powershell_<RID>.inc命名,Windows 与 Linux 文件名不同以支持同机 WSL 构建); - 编译发布:核心命令为
dotnet publish /property:GenerateFullPaths=true ...。对 Windows 系 RID(win7-*、win-arm64,非最小体积构建)会设置SDKToUse=Microsoft.NET.Sdk.WindowsDesktop,从而引入 WPF/WinForms 及 PowerShell GraphicalHost 程序集(即Out-GridView等图形化功能);自包含构建加--self-contained; - 后置任务:发布引用程序集到
ref目录、按-PSModuleRestore恢复 Gallery 模块、生成powershell.config.json(Windows 构建会写入Microsoft.PowerShell:ExecutionPolicy = RemoteSigned等键)、清理多余原生存档等。
其中有一处值得注意的细节:从 .NET 8 起 SDK 默认不再识别 win7-x64 这类带版本号的 RID,构建脚本因此对 win* RID 追加 /property:UseRidGraph=true,沿用旧的完整 RID 图,以保持 win7-x64/win7-x86 这套 RID 约定不变。
定位与运行构建产物
构建成功后,可执行文件位于:
./src/powershell-win-core/bin/Debug/net6.0/win7-x64/publish/pwsh.exe
注意:该路径的框架段以仓库当前状态为准。原编写时期默认框架为
net6.0,当前仓库 build.psm1 中New-PSOptions的Framework参数默认值已更新为net11.0,因此当前实际路径中框架段为net11.0。
路径遵循统一形式 ./[project]/bin/[configuration]/[framework]/[rid]/publish/[binary name]:
| 段 | 默认值 | 说明 |
|---|---|---|
| project | powershell-win-core |
Windows 下顶层宿主项目(Unix 为 powershell-unix) |
| configuration | Debug |
可取 Debug/Release/CodeCoverage/StaticAnalysis |
| framework | 当前仓库默认 net11.0 |
由 New-PSOptions 决定 |
| rid | win7-x64 |
未指定时按本机平台与架构自动探测 |
| binary name | pwsh |
Windows 下为 pwsh.exe |
函数 Get-PSOutput 会返回该可执行文件路径,因此无需手拼路径,直接:
& (Get-PSOutput)
即可运行刚构建的开发版 PowerShell。Get-PSOutput 的解析优先级为:显式传入的 Options 表 → 上一次 Start-PSBuild 缓存的 $script:Options → 现场调用 New-PSOptions 计算。
powershell-win-core 项目就是 .NET 上的 PowerShell 宿主,是顶层项目,dotnet build 会传递性地构建它的全部依赖并产出 pwsh 可执行文件。从 src/powershell-win-core/powershell-win-core.csproj 可以看到它的构成:AssemblyName 为 pwsh、OutputType 为 Exe,编译共用的 src/powershell/Program.cs(跨平台主机入口,支持 --help 内置文档),并以项目引用方式依赖 Microsoft.PowerShell.SDK、Microsoft.PowerShell.Commands.Diagnostics、Microsoft.Management.Infrastructure.CimCmdlets、Microsoft.WSMan.Management,而图形化的 Microsoft.PowerShell.GraphicalHost 仅在 SDKToUse == Microsoft.NET.Sdk.WindowsDesktop 时才被引入。此外,项目还会把 src/Modules/Windows、src/Modules/Shared 下的模块文件、dsc/ 资源、GroupPolicy 模板等一并复制到发布目录。
运行 Pester 测试
构建完成后,用 Start-PSPester 运行跨平台 Pester 测试:
Import-Module ./build.psm1
Start-PSPester -UseNuGetOrg
-UseNuGetOrg 会在测试前将 NuGet 配置切换为公共源(因为还原 Pester 等测试依赖同样需要访问 NuGet)。从 Start-PSPester 的参数与实现看,有几个对 Windows 使用者有意义的默认行为:
- 默认测试路径为
test/powershell目录,包含标签CI与Feature,排除标签Slow; - 若当前用户不是管理员,会自动追加排除
RequireAdminOnWindows标签,避免需要提权的测试失败;管理员环境则可显式-Unelevate在非提升子进程中运行测试; - 若本地没有 Pester(要求 4.2 及以上),
Restore-PSPester会通过Save-Module从 PowerShell Gallery 拉取至构建输出的Modules/Pester目录(上限 4.99 版,即 Pester v4 系列); - 测试启动前会先发布测试辅助工具(
Publish-PSTestTools),并在子进程中设置POWERSHELL_TELEMETRY_OPTOUT='yes'、将test/tools/Modules注入PSModulePath,Windows 下还会执行Set-ExecutionPolicy -Scope Process Unrestricted; - 结果以 NUnit XML 格式输出(默认
pester-tests.xml),可通过-Quiet/-Terse控制输出详略。
关于在 Visual Studio 中直接构建
原指南最后提到,用 Visual Studio 集成环境构建源码的诉求由上游 issue 持续跟踪,社区版 VS 可打开 PowerShell.sln 浏览代码与调试,但正式构建仍建议走 build.psm1 模块路径——因为 Start-PSBuild 中大量的 /property: 注入(如 SDKToUse、AppDeployment、UseRidGraph)都是脚本侧动态决定的,直接在 IDE 里 F5 构建容易因缺少这些属性或版本检查而产生与脚本构建不一致的产物。
小结与常见问题
- SDK 版本不匹配:
Start-PSBuild会在版本不符时给出明确提示,按提示删除本地旧安装目录、重跑Install-Dotnet后再Start-PSBuild -Clean即可; - NuGet 还原失败:优先加
-UseNuGetOrg切换到公共源;若必须使用私有源,可用-InteractiveAuth触发交互式认证(对应dotnet restore --interactive); - 只改引擎想快速验证:
Start-PSBuild -SMAOnly可只重编System.Management.Automation.dll,跳过全部后置任务; - 产物路径不确定:始终用
Get-PSOutput获取,不要手写路径——它会自动跟随当前 RID、配置与框架版本。
相关延伸阅读:Linux 构建指南、macOS 构建指南、构建内部机制。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00