5

背景

我们有一个用 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对象的线程模型吗?

4

2 回答 2

2

您可以使用以下命令转储线程状态:

~*

这不会将“背景”显示为状态,您只会看到正在运行、冻结或暂停。

我不确定您如何从 COM 对象获取信息,我从未尝试过,但会调查并回复您,关于线程模型,如果没有在单步执行后对应用程序状态进行痛苦的监控,即使使用那,当你单步执行所有其他线程时,除非你使用.bpsync 1which 将所有线程同步到当前线程,否则它将运行,但这可能会导致挂起(例如,gui 线程现在被告知冻结)所以我认为除非你有访问源代码。

于 2012-05-18T09:50:45.673 回答
1

我只能回答问题 1。!runaway用于查找消耗 CPU 的线程。要获取所有线程堆栈,请使用~*kb1000.

于 2012-05-17T14:39:15.063 回答