ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

WinUI 崩溃调试实战指南:在 microsoft-ui-xaml 中获取崩溃转储并解析 Stowed Exception 调用栈

WinUI 崩溃调试实战指南:在 microsoft-ui-xaml 中获取崩溃转储并解析 Stowed Exception 调用栈 WinUI 崩溃调试实战指南在 microsoft-ui-xaml 中获取崩溃转储并解析 Stowed Exception 调用栈【免费下载链接】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本文基于 WinUI 仓库中面向外部贡献者的崩溃调试文档 debugging_crashes.md系统讲解两件事如何用 Visual Studio、WinDbg 或 Windows 错误报告WER获取崩溃转储crash dump以及如何为不同类型尤其是 stowed exception异常码 0xc000027b的崩溃提取出真正有诊断价值的调用栈。读完本文你可以独立完成 WinUI 应用的崩溃复现、转储采集、cdb 自动分析与提 issue 全流程并理解 WinUI 底层“暂存异常”机制为何让 PDE 调试器扩展成为必备工具。1. 崩溃调试在 WinUI 中的典型场景WinUI 是混合技术栈应用层可能是托管代码C#而 XAML 框架核心dxaml目录下的 C 实现是纯原生代码。这意味着崩溃点往往落在原生层调试器必须以Native或混合Managed Native模式附加纯托管模式看不到真正的问题现场崩溃形式不只是访问违例access violation更常见的是 WinUI 特有的stowed exception暂存异常异常码0xc000027b——框架先把错误“存起来”稍后若无人处理才将其升级为致命错误此时直接看到的崩溃栈通常已经失真。本文两大主线分别对应这两个问题如何拿到崩溃转储第 2 节与如何拿到正确的调用栈第 3 节。2. 如何获取崩溃转储How to get a crash dump2.1 使用 Visual Studio当崩溃发生在你自己的应用、且可以用 Visual Studio 启动或者能在崩溃前附加到应用时按以下步骤操作启动前配置调试模式若从 Visual Studio 启动应用启动前将调试模式设为“Native Only”或“Mixed (Managed and Native)”若附加到已在运行的进程在 “Attach to Process” 对话框中确认 “Attach to:” 设置包含“Native”若进程未显示该选项需手动切换类型后再附加。执行复现步骤Run the repro。崩溃发生后Visual Studio 会中断在崩溃处此时从Debug 菜单选择 “Save Dump As...”保存转储文件。注意事项文档明确指出Visual Studio 的 Diagnostic Tools 在某些情况下会引入“仅在 VS 调试且 Diagnostic Tools 开启时才出现”的崩溃。这类崩溃的典型特征是崩溃栈上某处出现包含Diagnostics的函数名或崩溃发生在独立的ScriptedSandbox64.exe进程中。若怀疑属于这种情况请在 Visual Studio 中关闭Tools | Options | Debugging | “Enable Diagnostic Tools while debugging”重新运行场景以排除调试工具自身引入的干扰。另外若需要以友好的方式查看xstring_ptr_view等 XAML 类型可以按 调试技巧文档 的说明将仓库提供的 scripts/winui.natvis 安装到 Visual Studio 的 Visualizers 目录后重启调试会话。2.2 使用 WinDbg在 WinDbg 中崩溃发生时执行以下命令即可保存完整内存转储到指定文件.dump /ma filename根据崩溃时机选择操作方式崩溃发生在应用启动之后先启动应用用 WinDbg 附加attach到应用进程然后执行复现步骤触发崩溃再执行.dump /ma崩溃发生在启动阶段推荐改用WinDbg Preview因为它的 “Start Debugging” 面板提供了“Launch app package”选项可以从应用启动时刻就开始调试 UWP 与打包packaged应用从而抓住启动期崩溃。2.3 让 Windows 在本地保留崩溃转储注册表方式如果不想依赖调试器常驻可以配置 Windows Error Reporting 自动在本地保存转储。在管理员权限的命令提示符中执行以下两条命令即可让 Windows 把完整fulltype2转储保存到C:\dumpsreg add HKLM\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps /v DumpFolder /d C:\dumps reg add HKLM\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps /v DumpType /t REG_DWORD /d 2参数说明注册表项作用取值说明LocalDumps\DumpFolder本地转储保存目录本文示例为C:\dumpsLocalDumps\DumpType转储类型REG_DWORD2表示完整内存转储full dump另有 mini、kernel 等类型可按需查阅 WER 官方文档复现崩溃后到指定目录即可找到生成的转储文件。2.4 自动化转储采集与提 issueanalyze-crash.ps1对于需要向 WinUI 仓库报告问题的外部用户官方提供了一个脚本可以一步完成“自动采集转储 cdb 分析 打开 issue 模板”的流程下载脚本通过官方短链aka.ms/RNW/analyze-crash.ps1例如下载到C:\temp打开管理员 PowerShell。如果尚未允许运行未签名脚本先执行Set-ExecutionPolicy Unrestricted运行脚本并传入应用 exe 名与仓库名C:\temp\analyze-crash.ps1 -ExeName MyApp -Repo microsoft/microsoft-ui-xaml脚本会自动完成以下事情为你的应用配置自动崩溃转储采集、下载原生调试工具包括命令行调试器cdb并提示你复现崩溃。随后启动应用例如已部署到本机时直接从开始菜单启动。应用崩溃时会生成崩溃转储.dmp文件按回车继续脚本执行脚本会用cdb自动分析该转储并把分析结果输出到analyze.log脚本接着把日志内容复制到剪贴板、用记事本打开日志文件并打开浏览器跳转到 WinUI 仓库的 issue 页面你可以直接把栈信息粘贴进 bug 模板提交。这条链路把“复现 → 采集 → 分析 → 提报”串成了半自动流程是外部贡献者上报 WinUI 崩溃问题成本最低的路径。2.5 补充WinUI 测试流水线中的转储文件从哪里找如果你是在 WinUI 仓库自身的 CI 测试中遇到崩溃而不是本地调试测试 FAQ 说明了转储的收集位置测试作业运行时会从测试机的c:\dumps目录收集最多 3 个转储并上传到该作业的artifacts工件中在工件页面里查找.dmp文件即可见文首截图中的TE.ProcessHost.exe(...).7896.dmp有时会在“通过”的作业中也看到崩溃转储原因通常是(a) 该测试被自动重跑且重跑通过或 (b) 崩溃发生在测试上报“通过”之后如果你预期有转储却找不到可能是该 exe 没有开启转储采集——需要检查 Helix/scripts/TestPass-OneTimeMachineSetup.ps1 中的$namesOfProcessesForDumpCollection变量文档还指出为了让转储采集生效需要配置 CI VM 禁用系统上处理崩溃的 CI agent避免它先一步截走intercept想要收集的转储。3. 如何为崩溃拿到正确的调用栈How to get a good callstack for crashes3.1 直接崩溃如访问违例对于访问违例access violation等直接崩溃崩溃时直接得到的调用栈通常就是正确的栈无需额外处理直接围绕栈顶分析即可。3.2 Stowed Exception 崩溃异常码 0xc000027bstowed exception暂存异常是 WinUI/XAML 框架特有的错误处理形态先把一个可能出现的错误“存起来”stow away只有当后续没有人处理该异常时才真正被抛出。这带来一个调试上的关键问题XAML 有时会在错误发生的第一时间就判定其为致命错误此时直接崩溃栈尚可参考但更常见的情况是调用栈在错误被判定为致命之前就已经展开unwind了此时崩溃处的直接栈往往指向的是“最终抛出点”而非“错误起源点”。对这类崩溃官方文档给出的标准做法是在 WinDbg 中加载崩溃转储后使用 PDE 调试器扩展转储暂存异常.load pde !pde.dsePDE 调试器扩展已包含在现代版本的 WinDbg 中.load pde加载后执行!pde.dse即可打印出 stowed exception 的完整信息。如何解读!pde.dse的输出文档给出的判读经验通常会出现多个stowed exception其中末尾的一些可能已被处理或被忽略经验上第一个 stowed exception 往往是最值得关注的那个个别情况下第一个 stowed exception 是第二个的re-throw重新抛出如果第二个 stowed exception 显示的位置比第一个更深、且在同一条栈上那么第二个才是错误的真正起源每个 stowed exception 附带的错误码同样很有价值它对应着该异常关联的HRESULT可据此反查框架文档或源码中的错误路径。3.3 源码印证为什么 PDE 扩展能看到 stowed exceptions从源码结构看!pde.dse之所以有效是因为 WinUI 在 fail-fast 时主动把线程上的暂存异常打包进了崩溃现场。在 dxaml/xcp/components/base/inc/minerror.h 中可以看到XAML_FAIL_FAST()宏在触发 fail-fast 前会调用GetStowedExceptionsForFailFast(ppStowedExceptions, cStowedExceptions)收集当前线程的暂存异常数组再调用FailFastWithStowedExceptions(hrError, cStowedExceptions, ...)将其连同错误 HRESULT 一起带入崩溃记录源码头部的注释明确解释了动机“When a user mode debugger is not present, pack up stowed exceptions to maximize the info available from dumps that dont have all the heap.”——即在没有调试器附加、甚至转储未包含全部堆内容的情况下也要把暂存异常信息固化进转储这正是 PDE 扩展能从 dump 里还原 stowed exceptions 的底层原因FAIL_ASSERT_HERE宏也被覆写为断言失败时若没有调试器IsDebuggerPresent() FALSE则走自定义的 fail-fast 流程打包错误信息从而保证转储中始终带有可诊断的上下文。此外暂存异常并非只存在于崩溃路径dxaml/xcp/core/error/ErrorEventArgs.cpp 在查询错误消息时使用了SuspendFailFastOnStowedException上下文对象说明“暂存异常 fail-fast”是贯穿 WinUI 错误处理链路的核心机制。因此遇到0xc000027b崩溃时用!pde.dse还原暂存异常列表本质上就是沿着框架自己埋好的错误现场信息倒推错误起源。4. 与其他调试文档的配合崩溃调试通常不是孤立步骤仓库内以下文档可与之配合使用docs/debugging/debugging-tips.mdLoader Snaps诊断 DLL 加载失败、WinDbg 时间旅行调试TTD、事件循环条件断点基于CEventManager::Raise打印事件、测试内存泄漏排查以及 TAEF 测试的/p:WaitForDebugger、/p:WaitForAppDebugger等待调试器附加参数docs/debugging/debugging.md如何在不同应用配置下覆盖 WinUI 二进制并调试私有构建包括.local/DLL 重定向DevOverrideEnable注册表 Application.Local目录、takeownicacls覆盖、PSExec 等方案——当崩溃只在特定二进制版本上出现时这些方法能把本地构建位注入到目标应用中复现。5. 速查表场景推荐工具关键操作可在 VS 中启动/附加的应用Visual Studio调试模式设为 Native Only / Mixed崩溃后 Debug → Save Dump As...启动期崩溃UWP/打包应用WinDbg PreviewStart Debugging → Launch app package崩溃后保留完整现场WinDbg.dump /ma filename无法常驻调试器WER 注册表LocalDumps下设置DumpFolder与DumpType2外部用户报 buganalyze-crash.ps1-ExeName MyApp -Repo microsoft/microsoft-ui-xaml自动 cdb 分析并打开 issue 模板直接崩溃访问违例等任意调试器直接采用崩溃处调用栈Stowed exception0xc000027bWinDbg PDE.load pde→!pde.dse优先看第一个暂存异常注意 re-throw 情形与 HRESULT6. 小结处理 WinUI 崩溃的核心方法论可以归纳为先拿转储再谈分析VSNative/Mixed 模式、WinDbg.dump /ma、WER LocalDumps 或 analyze-crash.ps1 四条路径覆盖从本地调试到无人值守采集的全部场景区分崩溃类型访问违例类直接崩溃直接看崩溃栈0xc000027bstowed exception 崩溃必须用 PDE 扩展.load pde!pde.dse还原暂存异常列表并依据“第一个暂存异常优先、注意 re-throw、关注 HRESULT”的原则定位真正的错误起源理解底层机制从 minerror.h 的XAML_FAIL_FAST()实现可以看到框架在 fail-fast 时主动打包暂存异常进转储!pde.dse的可用性与框架自身实现一脉相承。掌握以上流程后无论是本地复现还是流水线失败你都能产出一份信息完整、可直接用于定位与提报的崩溃分析结果。【免费下载链接】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),仅供参考
返回列表