背景
我们有一个用 C# 编写的 .NET WinForms 应用程序,它通过控制台应用程序连接到手持式商店扫描仪。控制台应用程序是用很好的 VB6 编写的——那里没有托管代码。VB6 应用程序由几个 COM 对象组成。
.NET WinForms 应用程序通过调用具有正确参数的控制台应用程序来刷新扫描仪中的数据。当控制台应用程序启动时,它会弹出一个模态表单,提醒用户将手持设备放入支架中。
问题
客户有一个奇怪的情况,启动控制台应用程序的调用在显示提醒表单之前似乎挂起。如果用户按下任何键——即使是像 Shift 或 Alt 这样的无害键——应用程序将解冻,并出现提醒表单。挂起时,控制台应用程序的 CPU 使用率非常高。
我们使用ProcDump从命令行应用程序获得了内存转储。我有一些调试托管转储文件的经验,但是这个 VB 6 转储对我来说很奇怪。
我们连续捕获了几个完整的内存转储。在其中一些中,似乎有 COM 胶水堆栈。例如,几个转储文件显示如下调用堆栈:
msvbm60!BASIC_DISPINTERFACE_GetTICount
msvbm60!_vbaStrToAnsi
msvbm60!IIDIVbaHost
msvbm60!rtcDoEvents
msvbm60!IIDIVbaHost
msvbm60!BASICCLASS_QueryInterface
[our code which I think is trying to create and invoke a COM object]
我拥有的唯一符号来自我们的代码,这无济于事。Microsoft 符号服务器没有用于 msvbm60.dll 的 PDB 文件(或者至少没有来自其版本 6.0.98.2)。
问题
我怀疑可能存在仅在他们的系统上发生的一些 COM 线程问题。
1)如何确定转储文件中每个线程的线程状态?如果这是一个托管转储文件,我会查看!threads
然后!threadstate
找出线程状态。没有托管代码,所以我不能使用 sos.dll。我没有看到任何使用~
and的提示!teb
。
2) 有没有办法查看在转储文件中创建了哪些 COM 对象?同样,在托管转储中,我可以执行 a!dumpheap
来获取托管对象的列表。我可以为 COM 对象找到类似的东西吗?
3) 我可以确定转储文件中COM对象的线程模型吗?