news 2026/9/16 13:20:39

WinUI (microsoft-ui-xaml) 调试实践:从本地构建到多部署配置下的私有二进制替换

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
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(默认)构建产品代码 + 测试代码(不含 samples)
product只构建产品代码(prodtest的子集)
mux只构建Microsoft.UI.Xaml.dllproduct的子集)
test只构建测试(prodtest的子集)
samples构建示例应用
all产品 + 测试 + samples 全部构建

常用选项(同样来自 Build.cmd 的帮助文本):

  • /restore:附加 NuGet restore;/c:构建前清理 bin/obj/temp/packaging 目录;
  • /muxfinal:设置MUXFinalRelease=true,模拟正式发布构建(关闭实验性功能);
  • /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 Gallery):docs/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且构建 Debug,WinUI 位会位于形如

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 --> <WindowsAppSDKSelfContained>true</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。

原文档给出的操作步骤(完整保留):

  1. 设置DevOverrideEnable注册表键:

    REG ADD "HKLM\Software\Microsoft\Windows NT\CurrentVersion\Image File Execution Options" /v DevOverrideEnable /t REG_DWORD /d 1

    注意:该设置需要重启才生效。

  2. 在目标包的已安装位置下创建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"
  3. 把你的覆盖 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 即可。)

  4. 对非打包(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 为例,原文档给出的完整命令(以管理员身份打开 PowerShell):

cd $(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\<arch><config>\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 PSExec(SYSTEM 提权替换)

另一种手段是借助 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重定向 或 takeown+icacls重定向不改原文件、可随时撤除;直接覆盖更彻底但破坏原包
Framework Package(WindowsAppRuntime).local重定向原文档明确 takeown 方式对其无效
非打包应用exe 旁建.exe目录加载器优先 exe 目录

五、延伸:更深入的诊断技巧与测试体系

docs/debugging/debugging.md 本身是入口性文档,它把两类更细的内容外链了出去(转换为仓库根相对路径):

  • docs/debugging/debugging-tips.md:VS 断点动作(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 的核心脉络可以归纳为一条主线:先构建,再让目标进程加载你的位

  1. build.cmd全量构建(默认prodtest),产品位 binplace 到BuildOutput\bin\<arch><config>\Product(见 eng/folderpaths.props);
  2. 仓库内样本:零配置,自动拾取BuildOutput
  3. VS 自包含应用:复制位到AppX\<AppName>,用 scripts/find-appx.ps1 定位;
  4. Store/第三方/框架包场景:DevOverrideEnable+Application.Local重定向为首选,takeown+icacls 用于直接覆盖,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),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/16 13:17:00

零代码单细胞全流程分析实战:从GEO数据到细胞注释

1. 零代码单细胞全流程分析&#xff0c;到底能做什么先说个在我圈子里反复出现的场景&#xff1a;实验室没有专职生信人员&#xff0c;师兄师姐懂一点R但只够处理bulk转录组&#xff0c;老板突然丢来一个单细胞项目&#xff0c;研究对象是临床样本&#xff0c;合作方只给了GEO登…

作者头像 李华
网站建设 2026/9/16 13:16:02

2026舟山化工产品成分分析检测排名 TOP5 CMA 资质提供含量检测、纯度检测、元素分析 联系方式推荐

舟山化工产品成分分析检测领域&#xff0c;实验室与检测机构鳞次栉比&#xff0c;但其中鱼龙混杂、良莠不齐。本地化工企业、新材料厂商、日化生产工厂、橡塑制造业以及食品医药企业的研发质检部门&#xff0c;在筛选服务商时稍有不慎&#xff0c;极易误入无正规资质的陷阱。这…

作者头像 李华
网站建设 2026/9/16 13:15:35

Mac Mouse Fix 使用指南:10分钟完成 macOS 鼠标增强与侧键映射

Mac Mouse Fix 使用指南&#xff1a;10分钟完成 macOS 鼠标增强与侧键映射 【免费下载链接】mac-mouse-fix Mac Mouse Fix - Make Your $10 Mouse Better Than an Apple Trackpad! 项目地址: https://gitcode.com/GitHub_Trending/ma/mac-mouse-fix Mac Mouse Fix 是一款…

作者头像 李华
网站建设 2026/9/16 13:15:33

OneUptime CLI 完整指南:多环境认证、资源 CRUD 与 CI/CD 自动化

OneUptime CLI 完整指南&#xff1a;多环境认证、资源 CRUD 与 CI/CD 自动化 【免费下载链接】oneuptime Complete open-source monitoring and observability platform. 项目地址: https://gitcode.com/GitHub_Trending/on/oneuptime 本文以 OneUptime 官方 CLI 文档&a…

作者头像 李华
网站建设 2026/9/16 13:15:32

10. 软件设计架构-微服务-服务配置

文章目录前言一、配置中心介绍1. 什么是配置中心2. 解决方案二、Nacos Config入门三、Nacos Config深入1. 配置动态刷新2. 配置共享四、nacos服务配置的核心概念前言 服务配置--Nacos Config‌ 微服务架构下关于配置文件的一些问题&#xff1a; 配置文件相对分散。在一个微服…

作者头像 李华