首页
/ PowerShell Windows 构建指南:.NET SDK 环境准备、Start-PSBuild 编译流程与产物定位

PowerShell Windows 构建指南:.NET SDK 环境准备、Start-PSBuild 编译流程与产物定位

2026-09-05 23:47:06作者:尤辰城Agatha

本篇基于仓库文档 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.psm1Install-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/sqlite3src/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/Modulestest/tools/Modules 三处重新生成 nuget.config,指向 nuget.org 与 dotnet 公共源,免去认证步骤。

构建流程内部发生了什么

Start-PSBuild 源码看,一次完整构建依次执行:

  1. 前置检查Find-Dotnet 将 .NET CLI 加入 PATH,precheck 校验 gitdotnet 均在 PATH 中,随后 Find-RequiredSDK 比对已安装 SDK 版本与 global.json 要求;若版本不符,函数会打印已安装/所需版本及三步修复指引(删除 $env:LOCALAPPDATA\Microsoft\dotnet 下旧版本、重跑 Start-PSBootstrapInstall-Dotnet、再执行 Start-PSBuild -Clean)后直接返回;
  2. 解析构建选项New-PSOptions 计算顶层项目目录、RID、框架与输出路径。未显式指定 -Runtime 时,它会从 dotnet --info 解析当前平台与架构,Windows x64 会得到 win7-x64、ARM64 得到 win-arm64;顶层项目目录对 Windows 系 RID 固定为 src/powershell-win-core
  3. NuGet 还原Restore-PSPackage 对顶层项目、src/TypeCatalogGensrc/ResGensrc/Modulestools/wix 五个目录执行 dotnet restore,每个项目带最多 5 次重试;Windows 系 RID 会追加 /property:EnableWindowsTargeting=True/property:UseRidGraph=True
  4. 代码生成:按需执行 Start-ResGen(为 resx 资源文件生成 C# 绑定)与 Start-TypeGen(生成 CorePsTypeCatalog.cs,按 powershell_<RID>.inc 命名,Windows 与 Linux 文件名不同以支持同机 WSL 构建);
  5. 编译发布:核心命令为 dotnet publish /property:GenerateFullPaths=true ...。对 Windows 系 RID(win7-*win-arm64,非最小体积构建)会设置 SDKToUse=Microsoft.NET.Sdk.WindowsDesktop,从而引入 WPF/WinForms 及 PowerShell GraphicalHost 程序集(即 Out-GridView 等图形化功能);自包含构建加 --self-contained
  6. 后置任务:发布引用程序集到 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.psm1New-PSOptionsFramework 参数默认值已更新为 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 可以看到它的构成:AssemblyNamepwshOutputTypeExe,编译共用的 src/powershell/Program.cs(跨平台主机入口,支持 --help 内置文档),并以项目引用方式依赖 Microsoft.PowerShell.SDKMicrosoft.PowerShell.Commands.DiagnosticsMicrosoft.Management.Infrastructure.CimCmdletsMicrosoft.WSMan.Management,而图形化的 Microsoft.PowerShell.GraphicalHost 仅在 SDKToUse == Microsoft.NET.Sdk.WindowsDesktop 时才被引入。此外,项目还会把 src/Modules/Windowssrc/Modules/Shared 下的模块文件、dsc/ 资源、GroupPolicy 模板等一并复制到发布目录。

运行 Pester 测试

构建完成后,用 Start-PSPester 运行跨平台 Pester 测试:

Import-Module ./build.psm1
Start-PSPester -UseNuGetOrg

-UseNuGetOrg 会在测试前将 NuGet 配置切换为公共源(因为还原 Pester 等测试依赖同样需要访问 NuGet)。从 Start-PSPester 的参数与实现看,有几个对 Windows 使用者有意义的默认行为:

  • 默认测试路径为 test/powershell 目录,包含标签 CIFeature,排除标签 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: 注入(如 SDKToUseAppDeploymentUseRidGraph)都是脚本侧动态决定的,直接在 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 构建指南构建内部机制

登录后查看全文
热门项目推荐
相关项目推荐