WinUI (microsoft-ui-xaml) 调试实践:从本地构建到多部署配置下的私有二进制替换
WinUI (microsoft-ui-xaml) 调试实践从本地构建到多部署配置下的私有二进制替换【免费下载链接】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本文基于仓库中 docs/debugging/debugging.md 整理聚焦 WinUI 仓库私有位private bits调试的核心工作流如何用根目录的 Build.cmd 完成一次完整的本地构建以及如何在你自己的 VS 应用、Store 部署应用等不同部署形态下把本地编译出的 WinUI 二进制替换或重定向进目标应用从而让调试器加载你自己的代码与 PDB。读完后你将掌握.localDLL 重定向、takeown/icacls直接覆盖、PSExec 提权替换三种实战方案及其各自的适用边界。一、前提先用 build.cmd 完成一次完整构建所有调试动作的前提是“手上有一份自己的产品二进制”。原文档明确要求You first need to perform a full build using thebuild.cmdscript in the root of the repo.Build.cmd 是仓库根目录的一键构建入口。从 Build.cmd 的 usage 部分可以看到它支持的构建目标target目标含义prodtest默认构建产品代码 测试代码不含 samplesproduct只构建产品代码prodtest的子集mux只构建Microsoft.UI.Xaml.dllproduct的子集test只构建测试prodtest的子集samples构建示例应用all产品 测试 samples 全部构建常用选项同样来自 Build.cmd 的帮助文本/restore附加 NuGet restore/c构建前清理 bin/obj/temp/packaging 目录/muxfinal设置MUXFinalReleasetrue模拟正式发布构建关闭实验性功能/b、/m控制 MSBuild 并行实例数后台模式 2 个 / 每核心 1 个/fake只打印将要执行的命令不实际构建/version ver覆盖WinUIVersion属性默认为3.0.0-dev见 Build.cmd 中的_version初始化。构建产物落在哪里BuildOutput 约定后文反复出现的“把 dll 复制到应用安装目录”其源目录就是构建输出。从 eng/folderpaths.props 可以确认产物路径的构成ArtifactsRoot默认为$(ProjectRoot)BuildOutput\即 Build.cmd 生成的所有二进制统一汇入BuildOutput\ProductBinplaceDestinationPath为$(CurrentEnvironmentSubDir)\Product而CurrentEnvironmentSubDir是$(MUXOutputPlatform)$(MUXOutputConfiguration)的拼接。这正是原文档示例路径BuildOutput\bin\x86chk\Product\的来源x86是平台NuGet 兼容命名chk是 Debug 配置。也就是说Debug x86 构建出的产品 dll含 PDB最终都会被 binplace 到BuildOutput\bin\x86chk\Product\Debug x64 对应amd64chk等组合。替换二进制时务必保证架构x86/amd64一致——原文档对此有明确提醒。配套文档构建示例应用与新建测试应用原文档在 Manual Testing 一节给出了三条延伸路径以下链接已转换为仓库根目录相对路径构建/调试仓库内任意示例应用含 WinUI Gallerydocs/building/building-sample-apps.md。其中说明了示例应用既能针对本地 WinUI 组件包构建也能针对已发布的Microsoft.WindowsAppSDKNuGet 包构建通过scripts\buildSample AppName version指定版本在仓库内创建一个使用本地位的新测试应用docs/building/building-new-repo-app.md在仓库外创建自己的 VS 应用并指向本地构建的快速内循环ad-hoc工作流docs/ad-hoc-testing-of-local-build-with-fast-inner-loop.md。该文档给出了完整的nuget.config配置方式让外部项目直接引用本地构建产出的组件包。另外Build.cmd 在完成产品构建后会调用 pack.component.cmd 生成一个本地 mock 组件包本地开发版命名为Microsoft.WindowsAppSDK.WinUI.3.0.0-dev.nupkg。仓库 Samples 目录下的示例应用正是通过 Samples/WinUIPackageReference.props 引用该包版本取$(WinUIVersion)从而把本地构建输出注入到示例应用里。二、在 xaml 仓库内部测试私有位这是最简单的情形。原文档指出如果你在 xaml 仓库中工作Samples\下的示例应用总是从BuildOutput拾取 dll。你只需要按常规方式构建一次 xaml 仓库然后重新构建任意一个示例应用即可。这与 Build.cmd 的流程一致build.cmd先构建 XAML 编译器前置工程XamlCompilerPrerequisites.sln再依次构建Microsoft.UI.Xaml.sln与 controls/MUXControls.sln最后samples目标调用 buildsamples.cmd 把示例应用链接到BuildOutput中的本地位上。整个链条中示例应用与产品二进制共享同一份BuildOutput不需要任何手动复制。三、在 VS 应用仓库外项目中覆盖 WinUI 二进制如果你写了自己的应用不在仓库 Samples 目录里做法非常直接把更新后的 WinUI 位复制到应用的安装位置而安装位置就在应用项目目录下。原文档给出的示例如果你的应用位于c:\repos\MyApp且构建 DebugWinUI 位会位于形如c:\repos\MyApp\MyApp (Package)\bin\x86\Debug\AppX\MyApp的目录中。通常 VS 的构建输出窗口会在某处显示该位置你也可以用scripts\find-appx脚本来定位应用安装位置。该脚本对应仓库中的 scripts/find-appx.ps1其实现是对get-appxpackage的结果按包全名和InstallLocation做子串匹配get-appxpackage | Where-Object { ($_.PackageFullName.ToLower().Contains($searchString)) -or ($_.InstallLocation -ne $null -and $_.InstallLocation.ToLower().Contains($searchString)) }所以scripts\find-appx WinUIGallery这样的调用即可找到 WinUI Gallery 的InstallLocation。例外应用走 Framework Package 时原文档特别强调如果你的 VS 应用是通过 Framework Package 方式消费 WinUI而不是自包含打包简单复制 AppX 目录里的 dll 可能不生效——此时应改用下文“.local与 DLL 重定向”方案按步骤 1–3a/3b 执行并把你的二进制放入 3b 指定的位置。这种场景在“缺陷只在 Framework Package 部署形态下复现、自包含部署形态下不复现”时尤其有用因为自包含打包无法覆盖 Framework Package 中的系统级二进制。四、在 Store 部署第三方应用中覆盖 WinUI 二进制对于你自己构建的应用在 .csproj 里把 WinUI 设为自包含通常更简单也更安全!-- .csproj of the app -- PropertyGroup ... !-- Set this property to point to your local WinUI details repo -- WindowsAppSDKSelfContainedtrue/WindowsAppSDKSelfContained /PropertyGroup但面对 Store 上或第三方安装的包你无法修改其项目文件就需要下面的三种手段。4.1 .local 与 DLL 重定向推荐可复用于开发场景该方式不是覆盖系统二进制而是利用 DLL 查找顺序让加载器“先找到你的副本”。它同样适用于开发场景例如本地构建过MUX.dll后F5 部署示例应用时也会顺带部署一份私有副本。原理带包身份package identity的应用进程在 DLL Search Order 中多出一个“第 0 步”——pkgdir\microsoft.system.package.metadata\Application.Local重定向目录前提是在注册表开启DevOverrideEnable。这是 Windows 8 应 shell 开发者的要求加入的机制专门用于快速测试打补丁的 DLL。原文档给出的操作步骤完整保留设置DevOverrideEnable注册表键REG ADD HKLM\Software\Microsoft\Windows NT\CurrentVersion\Image File Execution Options /v DevOverrideEnable /t REG_DWORD /d 1注意该设置需要重启才生效。在目标包的已安装位置下创建microsoft.system.package.metadata\Application.Local目录MD C:\Program Files\WindowsApps\Microsoft.WindowsCalculator_11.2206.0.0_x64__8wekyb3d8bbwe\microsoft.system.package.metadata\Application.Local把你的覆盖 DLL 复制到该位置COPY C:\PrivateLocalBuild\shell32.dll C:\Program Files\WindowsApps\Microsoft.WindowsCalculator_11.2206.0.0_x64__8wekyb3d8bbwe\microsoft.system.package.metadata\Application.Local\把shell32.dll换成你本地构建的Microsoft.UI.Xaml.dll等产品 dll 即可。对非打包unpackaged应用可以在 exe 旁边创建同名.exe目录放入本地二进制。例如为explorer.exe创建c:\windows\explorer.exe.local其中任何 DLL 都会替代系统二进制。原文档附带的两条重要注释NOTE: This Application.Local trick applies to all packages no matter their source or install location. Long as the process has package identity andDevOverrideEnableis set, the Loader looks here before anywhere else (even before APIsets!)NOTE: If deploying a packaged app through Visual Studio, you will still need to follow step 4 below too, to create a.exefolder withinAppxfolder but copy dlls to location mentioned in step 3 only. You can useModulesview within VS to check the location of loadedMicrosoft.ui.xaml.dllto verify if the trick worked.即通过 VS 部署打包应用时仍需要在Appx文件夹中创建一个.exe目录但 dll 只复制到步骤 3 的位置最后用 VS 的 Modules 视图确认Microsoft.UI.Xaml.dll的实际加载路径来完成验证。4.2 takeown icacls直接覆盖应用 DLL该方式直接改写已安装应用的 DLL。以替换从 Store 安装的 WinUI Gallery 所用的 DLL 为例原文档给出的完整命令以管理员身份打开 PowerShellcd $(get-appxpackage Microsoft.WinUIGallery).InstallLocation takeown /f * icacls * /grant:r administrators:f copy product directory*.dll其中product directory即你的构建产物目录原文档举例copy repo-root\BuildOutput\bin\x86chk\Product\*.dll要点架构必须匹配x86/amd64对应第一节中BuildOutput\bin\archconfig\Product的目录约定可以用scripts\find-appx定位应用安装位置例如scripts\find-appx WinUIGallery然后cd $(scripts\find-appx WinUIGallery).InstallLocation原文档明确警告该方式无法用于替换 Framework Package即...\WindowsApps\Microsoft.WindowsAppRuntime*的内容此类场景应使用 4.1 的.local与 DLL 重定向方案。4.3 PSExecSYSTEM 提权替换另一种手段是借助 SysInternals PSExec在提权命令提示符中执行PSExec.exe -s cmd进入 SYSTEM 账户的命令行从而拥有对WindowsApps目录执行xcopy等文件操作的权限。原文档对此方案的定性是unsupported可能引发问题例如 Windows Defender 开始告警“This option comes with large responsibility and improper usage can corrupt windows installation”——使用不当可能损坏 Windows 安装。因此应把它作为最后手段。4.4 三种方案如何选择场景推荐方案原因仓库内 Samples 示例应用直接构建示例应用自动从BuildOutput拾取本地位自己写的 VS 自包含应用复制 dll 到AppX\MyApp或设WindowsAppSDKSelfContained无权限障碍最直接自己写的 VS 应用Framework Package 形态.local重定向无法用自包含打包替换二进制Store/第三方打包应用.local重定向 或 takeownicacls重定向不改原文件、可随时撤除直接覆盖更彻底但破坏原包Framework PackageWindowsAppRuntime仅.local重定向原文档明确 takeown 方式对其无效非打包应用exe 旁建.exe目录加载器优先 exe 目录五、延伸更深入的诊断技巧与测试体系docs/debugging/debugging.md 本身是入口性文档它把两类更细的内容外链了出去转换为仓库根相对路径docs/debugging/debugging-tips.mdVS 断点动作Trace串联事件链、ntdll.dll!LdrpDebugFlags的 Loader Snaps 排查模块加载失败、winui.natvis调试器可视化、dbgsrv 跨机调试、Time Travel Debugging、测试内存泄漏定位XcpCheckLeaks断点 dps/dqs转储分配栈、CEventManager::Raise上的事件循环条件断点等docs/testing/testing-FAQ.md 与 docs/testing/test-system-overview.md通用测试调试指引例如测试基础设施支持的/p:WaitForDebugger运行时参数让 TAEF 测试宿主等待调试器附加后再执行。需要说明的是原文档目录中还列有“Testing changes to Lifted IXP (including the FrameworkUDK)”与“Testing changes to WinUI Details”两个主题但当前仓库的该文档中这两节尚无正文内容属于待补全的占位条目本文不对其展开。六、小结围绕 docs/debugging/debugging.md 的核心脉络可以归纳为一条主线先构建再让目标进程加载你的位。build.cmd全量构建默认prodtest产品位 binplace 到BuildOutput\bin\archconfig\Product见 eng/folderpaths.props仓库内样本零配置自动拾取BuildOutputVS 自包含应用复制位到AppX\AppName用 scripts/find-appx.ps1 定位Store/第三方/框架包场景DevOverrideEnableApplication.Local重定向为首选takeownicacls 用于直接覆盖PSExec 仅作为不受支持的兜底。掌握这套“构建—部署形态—二进制替换”的映射关系就是在 WinUI 仓库中调试私有位的基本功更细的诊断手段加载日志、时间旅行调试、测试等待调试器附加则可继续参照 docs/debugging/debugging-tips.md 与测试 FAQ 深入。【免费下载链接】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),仅供参考