拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

WinUI 构建版本体系避坑指南:packages.config、RS5 最低目标与 .NET SDK 钉死机制

WinUI 构建版本体系避坑指南:packages.config、RS5 最低目标与 .NET SDK 钉死机制 WinUI 构建版本体系避坑指南packages.config、RS5 最低目标与 .NET SDK 钉死机制【免费下载链接】microsoft-ui-xamlWinUI: a modern UI framework with a rich set of controls and styles to build dynamic and high-performing Windows applications.项目地址: https://gitcode.com/GitHub_Trending/mi/microsoft-ui-xaml在 microsoft-ui-xaml 里改一个依赖版本号翻车的方式不止一种只动了中央包清单却漏掉分架构文件构建直接抛Version mismatch between arch-specific and arch-neutral Microsoft.Windows.SDK.cpp升级了 CSWinRT 却没同步eng\versions.props得到的是Version mismatch for Microsoft.Windows.CsWinRT between packages.config and versions.props还有一种更隐蔽的——全新克隆仓库后 NuGet 还原莫名其妙失败而你的同事复现不出来。下面沿着包从哪来 → 版本写在哪 → 版本为什么不能随便改 → 谁来集中读版本 → 示例应用怎么选运行时 → 升级依赖跑什么命令这条线把这五类问题一次讲透并在文末给出一张改版本 → 动文件的速查表。构建时 NuGet 包到底从哪个源来WinUI.Dependencies 主源与上游源机制结论先行全仓库只允许两个包源——远端的WinUI.Dependencies和本地的packagestore目录别的源一律不得直接添加。NuGet.config 里写得很直白packageSources clear / !-- DONT ADD NEW FEEDS TO THIS LIST -- !-- Instead set the feed as an upstream of this feed, or push the required nupkg to this feed. -- add keyWinUI.Dependencies valuehttps://pkgs.dev.azure.com/shine-oss/microsoft-ui-xaml/_packaging/WinUI-Dependencies/nuget/v3/index.json / add keypackagestore valuepackagestore / /packageSources这里有个值得理解的设计叫上游源upstream source你不需要把某个第三方源直接写进自己的 NuGet.config而是让 Azure DevOps 把那个源配置为WinUI.Dependencies的上游由主源代为引用和缓存。这样做的好处是源清单收敛在一个地方审计和变更都只对着一个 feed 发生所以配置文件里的注释才敢用大写警告不要在列表里加新源——要么把新源设为上游要么把需要的 nupkg 直接推进WinUI.Dependencies。那为什么还要留一个本地源因为 Azure DevOps 的 Upstream Sources 特性并不支持所有源类型只认 Azure DevOps 或公共源。packagestore这个指向 PackageStore/ 目录的本地源就是给内循环留的口子把 nupkg 往 PackageStore/ 目录里一放就能还原测试不必先推送到远端调试依赖时能省掉整个发布往返。版本声明在哪中央清单 packages.config 与三个分架构文件C 侧的全部 NuGet 依赖集中在仓库根目录的 packages.config。文件头部的注释就声明了两件事其中若干版本必须与eng\versions.props保持同步此外还存在分架构的包配置文件。当前清单版本与 eng/Versions.props 交叉验证一致如下包版本用途Microsoft.Windows.SDK.cpp10.0.22621.755C 工程消费的 Windows SDKNuGet 分发版Microsoft.Windows.SDK.Contracts10.0.17763.1000语言投影用的 SDK 元数据故意固定在 RS5Microsoft.NETCore.UniversalWindowsPlatform6.2.11.NET Native 全部组件的元包Microsoft.Taef10.100.251104001TAEF 测试框架Microsoft.Diagnostics.Tracing.TraceEvent2.0.45性能追踪MUXCustomBuildTasks1.0.125-winui3构建自定义任务Microsoft.Windows.ImplementationLibrary1.0.231028.1WILMicrosoft.Windows.CsWinRT2.1.1C#/WinRT 运行时须与Samples\WinUIGallery\WinUIGallery\standalone.props同步Microsoft.SourceLink.AzureRepos.Git1.1.0源码链接Microsoft.VCRTForwarders.1401.0.6TAEF 部署到 Helix 机器所需Microsoft.Internal.WinUILocalizationResources3.0.0-experimental.251103.0本地化 MUI 与 reswMicrosoft.Windows.SDK.BuildTools10.0.22621.3233makeappx.exe 等构建工具Microsoft.Windows.AbiWinRT2.0.210330.2winmd 转 ABI 头文件Microsoft.Internal.Windows.TestInProduction0.1.5TestInProduction 存根库Microsoft.MSBuildCache.Local/.AzurePipelines0.1.268-preview项目缓存Microsoft.Web.WebView21.0.3719.77WebView2及 BuildTools.MSIX 现为 WinAppSDK 传递依赖Microsoft.Windows.SDK.BuildTools.MSIX1.7.20250508.1MSIX 构建工具除了中央清单仓库还有三个按架构拆开的文件packages.x86.config、packages.x64.config、packages.arm64.config各自只声明一条Microsoft.Windows.SDK.cpp.x86/x64/arm64的引用当前三者版本号完全一致10.0.22621.755。必须一致不是口头约定而是构建期的硬校验。eng/Versions.props 会先按当前$(Platform)选定packages.$(Platform).config找不到时回退到 x86 文件用正则提取其中的Microsoft.Windows.SDK.cpp.*版本再与 packages.config 里的架构无关版本逐一比对。只要两者差一个补丁号构建就报Version mismatch between arch-specific and arch-neutral Microsoft.Windows.SDK.cpp——所以升 SDK 时中央清单和三个分架构文件必须同一次提交里改齐。Windows SDK 的两种装法以及为什么最低目标版本被锁死在 RS5先说 SDK 本身的分发。Windows SDK 有两条进仓库的路一是MSI 安装落在C:\Program Files (x86)\Windows Kits\...二是NuGet 还原Microsoft.Windows.SDK.cpp包还原到%RepoRoot%\packages\Microsoft.Windows.SDK.cpp。项目间写法可能不完全相同但 WinUI 的总体策略是工具链一律使用最新版本的 Windows SDK 构建当前即 10.0.22621.755。但用最新 SDK 构建和最低支持哪个系统版本是两回事。所有 WinUI 二进制的最低支持downlevel limit必须锁定在 Windows App SDK 的下限——Windows 10 1809 Redstone 5RS5对应NTDDI_WIN10_RS50x0A000006、UAP 契约 v7.0、Windows SDK 10.0.17763.0。这意味着默认情况下所有 C Win32、C ABI、C/WinRT、C#/WinRT 与 IDL 源码都必须面向 RS5 编译。约束有三个强制落点。第一packages.config 里Microsoft.Windows.SDK.Contracts固定为10.0.17763.1000注释原话是 fixed at RS5 (WinAppSDK downlevel limit)——语言投影元数据只从packages\Microsoft.Windows.SDK.Contracts.10.0.17763.1000\ref\netstandard2.0拉取。第二dxaml/Xaml.Cpp.Targets 在编译参数里写明 Windows App SDK supports downlevel to Windows 10 1809 Redstone 5并设置NTDDI_VERSIONNTDDI_WIN10_RS5。第三eng/lightup.targets 在XamlLightup不为true时清空TargetPlatformWinMDLocation、关闭ImplicitlyExpandTargetPlatform与CppWinRTImplicitlyExpandTargetPlatform并把引用解析重定向到 RS5 契约 winmd该文件由根目录 Directory.Build.targets 无条件导入Import Projecteng\lightup.targets /每个工程都能感知这个开关只是默认关闭。如果某段代码确实需要更新版本的 API——典型例子是 19H110.0.18632.0 / UAP v8.0引入的自动隐藏滚动条——工程可以定义XamlLightup项目属性为true来绕过最低目标约束让它面向当前 Windows SDK的元数据。代价是这类代码面向的版本高于产品承诺的最低线文档要求谨慎使用并且只允许放在明确标识为 light-up 代码的独立源文件里防止一个工程级属性悄悄抬高其他文件的目标版本。eng/Versions.props 的三个职责正则读版本、编译期校验、派生关键属性eng/Versions.props 是整个版本体系的总机做三件事。第一把版本从包文件里读出来。它在构建时用 MSBuild 表达式读取 packages.config、packages.$(Platform).config和 eng/Version.Details.xml 的文本内容用正则抽取版本号生成属性PackagesConfigContents$([System.IO.File]::ReadAllText($(PackagesConfigFile)))/PackagesConfigContents MicrosoftCsWinRTVersion$([System.Text.RegularExpressions.Regex]::Match($(PackagesConfigContents), Microsoft.Windows.CsWinRT.*?version(.*?)).Groups[1].Value)/MicrosoftCsWinRTVersion收益是包版本只在 packages.config 一处维护构建脚本和工程文件通过属性间接引用省掉多处手工同步。第二构建早期做一致性校验。ValidatePackageVersionRetrieval目标挂在Build;CoreCompile;Midl;ResolveAssemblyReferences之前查两类问题提取完整性——任何关键属性为空就报Unable to determine version for package Microsoft.Windows.SDK.cpp这类错误跨文件一致性——例如Error Condition$(MicrosoftCsWinRTVersion) ! $(MicrosoftCsWinRTPackageVersion) TextVersion mismatch for Microsoft.Windows.CsWinRT between packages.config and versions.props / Error Condition$(WebView2Version) ! $(WebView2PackageVersion) TextVersion mismatch for Microsoft.Web.WebView2 between packages.config and versions.props /也就是说只改了 packages.config 里的 CSWinRT 或 WebView2 版本而漏改 eng/Versions.props 中对应的MicrosoftCsWinRTPackageVersion2.1.1、WebView2PackageVersion1.0.3719.77构建会在早期直接失败而不是留下静默的版本漂移。第三由版本派生一批全仓库属性。摘几条关键的PackageTargetPlatformVersion$(MicrosoftWindowsSDKCppVersion.Substring(0,$(MicrosoftWindowsSDKCppVersion.LastIndexOf(.)))).0/PackageTargetPlatformVersion WindowsTargetPlatformVersion Condition$(WindowsTargetPlatformVersion)$(WindowsSdkTargetPlatformVersion)/WindowsTargetPlatformVersion WindowsAppSdkTargetPlatformVersion10.0.17763.0/WindowsAppSdkTargetPlatformVersion WindowsAppSdkTargetFrameworkMonikernet6.0-windows$(WindowsAppSdkTargetPlatformVersion)/WindowsAppSdkTargetFrameworkMoniker SamplesTargetFrameworkMonikernet8.0-windows$(WindowsAppSdkTargetPlatformVersion)/SamplesTargetFrameworkMoniker dotNetSdkChannel9.0.3xx/dotNetSdkChannelPackageTargetPlatformVersion从Microsoft.Windows.SDK.cpp版本号裁掉尾段拼上.0得到当前即 10.0.22621.0并作为全仓库默认WindowsTargetPlatformVersionWindowsTargetPlatformMinVersion缺省时落到 10.0.17763.0与 RS5 约束呼应。最值得玩味的是两个 TFMWindowsAppSdkTargetFrameworkMoniker注释写明出于兼容原因必须始终是 .NET 6因为它决定 Microsoft.WinUI.dll 的 CSWinRT 投影程序集面向哪个 .NET 版本而SamplesTargetFrameworkMoniker被有意解耦到 net8.0——.NET 6 已停止支持示例需要更新的运行时才能用required成员、init-only setter 这类较新 C# 特性。另外文件里有一块Condition$(IsInternalWinUIBuild) ! true的条件区域注释标明 OSS builds currently pin to last-known-good versions公开构建下 Foundation/IXP/Base/WinUIDetails 等传输包版本被固定为 last-known-good 值保证公开克隆可复现。示例应用怎么选 .NET 与 SDKTFM、FrameworkReference 覆盖与 NU1505C# 应用示例应用、XCG 等用 TFM 同时选定 .NET 版本和 Windows SDK 版本写法是net6.0-windows10.0.18362.0这种net6.0定 .NET10.0.18362.0定 SDK。当前仓库里示例应用实际用的是SamplesTargetFrameworkMoniker即net8.0-windows10.0.17763.08 .NET 810.0.17763.0 面向 RS5 最低目标。TFM 里的 SDK 版本可以被FrameworkReference项覆盖但仓库里不需要每个 csproj 各自写一遍根目录 Directory.Build.targets 被所有项目隐式导入其中一行Import Projecteng\sdkconfig.targets /引入 eng/sdkconfig.targets。该文件按TargetPlatformVersion加上MicrosoftWindowsSDKNetRefPackVersionSuffixOverrideeng/Versions.props 中当前定义为38组合出固定版本如 10.0.17763.38先移除 SDK 自带的隐式引用再显式包含FrameworkReference RemoveMicrosoft.Windows.SDK.NET.Ref;Microsoft.Windows.SDK.NET.Ref.Windows / FrameworkReference IncludeMicrosoft.Windows.Windows.SDK.NET.Ref TargetingPackVersion... /两个名字都移除是因为 .NET 9 起包更名成了Microsoft.Windows.SDK.NET.Ref.Windows。显式覆盖会引发一个容易吓人的告警NU1505重复的 PackageDownload.NET SDK 自带一份隐式的 SDK.NET.Ref你显式钉的另一个补丁版本也会转成 PackageDownload 条目两者在 NuGet 眼里重复了。这属于信息性告警——真正决定运行时用的是哪个版本的是显式的 Remove/Include——所以 eng/sdkconfig.targets 直接在NoWarn里把它关掉注释里讲清楚了来龙去脉。同一文件还处理了另一个漂移源全局 .NET SDK 装的是什么和构建时用什么是两码事。.NET 8 的目标包Microsoft.NETCore.App.Ref等从不被显式引用补丁版本由 SDK 自带的KnownFrameworkReference表决定而 SDK 是按通道dotNetSdkChannel9.0.3xx而非精确版本安装的不同贡献者、不同日期跑 init 拿到的补丁版本各不相同。eng/sdkconfig.targets 于是把所有 .NET 8 包族targeting、runtime、apphost、crossgen2、ILCompiler统一钉到Net8TargetingPackVersion当前8.0.28条件刻意限定在 v8.0net9.0 项目继续用各自的包。注释解释了动因OSS 构建从 shine-oss 源恢复这些包而该源只带显式发布过的版本漂移的补丁版本会让全新克隆还原失败——这正是开头同事能还原、你不能的常见根因。真正决定这台机器构建时用哪个 .NET SDK的是仓库根目录的 global.jsonsdk: { version: 9.0.313, rollForward: latestMajor, allowPrerelease: true }, msbuild-sdks: { Microsoft.Build.NoTargets: 3.3.0, Microsoft.WinAppSDK.EngCommon: 1.7.240708 }文件头部注释说明了策略version应始终设为当前 .NET 9 SDKrollForwardlatestMajor允许在已下载更高版本时向前滚动但 init 流程指定的 .NET 版本始终被尊重较新的 SDK 也能产出 .NET 9 应用。msbuild-sdks段里Microsoft.Build.NoTargets供只需要 binplace 等构建操作、并不真正需要 .NET 的 SDK 风格项目使用Microsoft.WinAppSDK.EngCommon供 Maestro 管理包与依赖。而实际装 SDK这一步由DownloadDotNetCoreSdk.ps1完成该脚本由 init.cmd 的初始化流程调用读取的就是 eng/Versions.props 里定义的 SDK 版本。升级依赖时跑哪条命令updateIxp、updateCswinrt 与 WebView2 更新脚本高频变动的依赖都配了升级脚本避免手工在多个文件间搬版本号。UpdateIxpscripts/updateIxp.cmd / scripts/updateIxp.ps1更新 Interactive ExperiencesIXP包引用触达packages*.config这一族文件。UpdateCSWinRTscripts/updateCswinrt.cmd / scripts/updateCswinrt.ps1同时修改 packages.config 与eng\versions.props中的 CSWinRT 版本——正好覆盖前文校验目标会比较的那对属性。UpdateWebView2更新 WebView2 SDK 与 Edge 版本的脚本触达controls\dev\dll\packages.config与eng\versions.props中的 SDK 包引用以及 packages.config、Edge 依赖 nuspec 与测试宿主 csproj 中的 Edge 版本相关说明见 controls/dev/WebView2/WebView2-update.md。速查要改哪个版本需要动哪几个文件想做的事必须同时改的文件漏改会怎样升Microsoft.Windows.SDK.cpppackages.config packages.x86.config / packages.x64.config / packages.arm64.config四个版本齐改Version mismatch between arch-specific and arch-neutral Microsoft.Windows.SDK.cpp升 CSWinRT 或 WebView2packages.config eng/Versions.props 里的MicrosoftCsWinRTPackageVersion/WebView2PackageVersionVersion mismatch for ... between packages.config and versions.props想跑新 C# 特性的示例eng/Versions.props 的SamplesTargetFrameworkMoniker勿动产品用的WindowsAppSdkTargetFrameworkMoniker它必须停在 net6产品投影程序集 TFM 漂移兼容性受损全新克隆还原失败先核对 eng/sdkconfig.targets 钉的Net8TargetingPackVersion/ SDK.NET.Ref 版本是否在 shine-oss 源上发布过再看 global.json 的 SDK 选择目标包补丁版本漂移源上没有对应版本代码必须面向 19H1 API独立 light-up 源文件 工程属性XamlLightuptrue未隔离时整工程最低目标被抬离 RS5记住一条主线就不会迷路packages.config 与分架构文件是声明处NuGet.config 定义从哪还原eng/Versions.props 负责读取、校验与派生RS5 由 dxaml/Xaml.Cpp.Targets 与 eng/lightup.targets强制Directory.Build.targets → eng/sdkconfig.targets 与 global.json 管C# 侧的版本落地升级脚本把多文件改动收敛成一条命令。 ️【免费下载链接】microsoft-ui-xamlWinUI: a modern UI framework with a rich set of controls and styles to build dynamic and high-performing Windows applications.项目地址: https://gitcode.com/GitHub_Trending/mi/microsoft-ui-xaml创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表