如何调试部署后触发AccessViolationException的COM集成C# WPF程序?
过去一周我一直在排查这个问题,翻了StackOverflow上不少关于AccessViolationException的帖子,但因为这个异常覆盖范围太广,没找到能直接套用的解决方案。
我开发了一个简单的C# WPF应用,核心功能是和一款外部应用的COM对象集成。为了分离UI和集成逻辑,我用Task创建工作线程处理信息、等待COM对象响应,所有和外部应用的交互都通过一个持有COM对象引用的静态类路由。程序基于.NET 8.0,用ClickOnce部署到服务器,运行时和依赖库都捆绑在安装包里,用户不用单独安装更新,简化了使用流程。
核心问题
在终端用户电脑上,应用连接COM应用后会因AccessViolationException崩溃(提示线程访问无权限内存),但我自己的电脑完全正常。COM应用会在后台启动,但几秒后整个进程就崩溃了。
程序启动后显示主窗口,点击按钮触发COM对象连接流程,验证通过后就能和外部应用交互。我给用户发了演示版,他们通过ClickOnce下载后,应用能正常启动,但点击打开COM接口的按钮就崩溃——崩溃发生在执行App = new ComApplication();之后(ComApplication是目标接口),能看到COM应用后台启动,但很快崩溃。
COM引用配置
我基于COM应用开发者提供的老旧且文档不完善的示例构建了COM接口引用,项目里添加了对他们的Interop.Application库的COM引用,设置了Embed Interop Types = Yes和Copy Local = Yes。观察发现Interop.Application库没嵌入到发布的程序集里,但用户电脑上已经注册了该COM接口。
崩溃点定位
通过日志追踪,崩溃发生在创建ComApplication实例后、调用其字段/方法之前(所有操作都在Task线程上执行):
App = new ComApplication(); if (App == null) { // 注:原代码中为`App = null`,应为笔误的相等判断 Logger.Error("Failed to open the Com Object!"); return false; } Logger.Info("COM object open!"); // 崩溃发生在这行日志之前 App.Visible = true; Logger.Info("COM app visible!");
崩溃转储分析问题
我发布了Debug配置的版本来获取更多信息,拿到了.dmp文件,错误信息是:0xC0000005: The thread tried to read from or write to a virtual address for which it does not have the appropriate access.
虽然在csproj里设置了DebugType为portable或embedded,但.dmp文件大小没变化,也没法通过自己的程序集源代码导航调用栈或找到PDB。自己程序集的“未找到所有符号”问题解决了,但部分NuGet包还是有这个问题,而且我的程序集提示“并非所有符号都有Source Link信息”——我不确定如果已经随应用发送了符号文件,Source Link还有什么作用,也不清楚对内部应用是否相关。
环境差异
关键是,程序在我自己的笔记本上完全正常,不管是ClickOnce部署运行还是Visual Studio 2022调试都没问题。我们用的是相同的操作系统、相同架构,而且.NET程序集已经嵌入,理论上运行时完全一致。
已完成的排查操作
- 移除了疑似导致崩溃的特定COM接口调用,发现任何对该接口的调用都会崩溃
- 添加逐行日志追踪程序运行步骤
- 发布Debug配置版本并将符号嵌入程序集
- 指定平台架构为x86而非AnyCPU,排查架构相关问题
- 计划在另一台工作站测试,但需要先安装COM应用
我对这个层级的编程比较陌生,不知道怎么利用崩溃转储文件获取更多崩溃时的信息,希望能得到帮助。
内容的提问来源于stack exchange,提问作者Chad V

