使用C#插件挂起COM应用程序

时间:2012-01-24 07:23:52

标签: c# com vb6 windbg minidump

我遇到了一个问题,我们的应用程序挂在客户的机器上,我已经连续几天没有解决。这个问题从我们所看到的情况中随机出现,尽管这可能不是真实的情况。客户还会报告应用程序挂起时CPU正在达到峰值。

问题是我不知道应用程序在哪里失败(挂起)。我们有几个用C#编写的插件作为主COM应用程序的插件。

我设法让客户在发生问题的机器上使用带有ProcExp的MiniDump。但是,就此而言,我对WinDBG或MiniDumps并不是很熟悉。我运行了!analyze -v!analyze -v -hang,它产生了一些输出,包括下面的堆栈。对于我能够分辨的内容,似乎应用程序正在转换到我们的一个C#插件(CLR),然后再转回到COM,它应该是一个返回插件可用的主应用程序的接口。但那又怎样?是否有可能从这个堆栈中说出更多内容?

如果重要的话,主要的应用程序是用VB6编写的。

0012da70 7e3693e9 7e3693a8 0012daf0 00000000 ntdll!KiFastSystemCallRet
0012da9c 7e37a43b 0012daf0 00000000 0000000f user32!NtUserPeekMessage+0xc
0012dac8 7348e6fd 0012daf0 00000000 0000000f user32!PeekMessageA+0xeb
0012db1c 77532a9c 00d03774 00000000 00000000 msvbvm60!CMsgFilter::MessagePending+0x21f
0012db60 77532a48 00000102 0012dbec 00000001 ole32!CCliModalLoop::HandlePendingMessage+0x40
0012dba8 7751eda6 80010116 80010115 00000000 ole32!CCliModalLoop::HandleWakeForMsg+0x46
0012dbbc 77547297 0012ddf0 00000001 0012dbe8 ole32!CCliModalLoop::BlockFn+0x8b
0012dc30 0ae8a2fd 00000002 00000001 00000001 ole32!CoWaitForMultipleHandles+0xcf
0012dc50 0ae8a264 00000000 00000001 00000001 mscorwks!NT5WaitRoutine+0x51
0012dcbc 0ae8a1c8 00000001 0012ddf0 00000000 mscorwks!MsgWaitHelper+0xa5
0012dcdc 0af3ccd0 00000001 0012ddf0 00000000 mscorwks!Thread::DoAppropriateAptStateWait+0x28
0012dd60 0af3cd65 00000001 0012ddf0 00000000 mscorwks!Thread::DoAppropriateWaitWorker+0x13c
0012ddb0 0ae8c026 00000001 0012ddf0 00000000 mscorwks!Thread::DoAppropriateWait+0x40
0012de00 0ae90f4c 00000001 05ae5c80 0012de60 mscorwks!Thread::JoinEx+0x86
0012de10 0b00ea40 00000001 00000001 5bdf0a2d mscorwks!Thread::Join+0x14
0012de60 0af0b9a7 00000001 0012deb0 0af0ba10 mscorwks!RCWCleanupList::CleanupWrappersInCurrentCtxThread+0x15a
0012de6c 0af0ba10 001df674 0012df10 5bdf0afd mscorwks!RCW::Initialize+0x78
0012deb0 0af0b6a7 001df674 0012df10 5bdf0b6d mscorwks!RCW::CreateRCW+0x84
0012df20 0af0b7b5 00000000 0012df5c 5bdf0b21 mscorwks!COMInterfaceMarshaler::CreateObjectRef+0x45
0012df6c 0ae892a8 5bdf3065 0012e6c8 0012e6c8 mscorwks!COMInterfaceMarshaler::FindOrCreateObjectRef+0xac
0012e428 0ae89444 001df658 11a11014 00000001 mscorwks!GetObjectRefFromComIP+0x1ec
0012e448 0ae894ab 05b3b0a8 001df658 0e896204 mscorwks!UnmarshalObjectFromInterface+0x19
0012e464 0af164d1 0012e6c8 0012e6ac 0af164c1 mscorwks!InterfaceMarshalerBase::ConvertSpaceNativeToCLR+0x30
0012e470 0af164c1 0012e748 0012e738 5bdf32e1 mscorwks!DefaultMarshalOverrides<InterfaceMarshalerBase>::ReturnCLRFromNativeRetval+0xb
0012e6ac 0aeb4bff 11741a76 0012e734 0012e74c mscorwks!RunML+0x9ac
0012e780 11740172 05ae5c80 0012e7d4 501b6046 mscorwks!CLRToCOMWorker+0x25f
...
... Stack begins down here in our main COM application.

编辑1: 阅读其他一些论坛帖子后我得到的一些想法。在我看来,挂起是在从.NET到COM的数据类型的编组之后引入的。现在我已经阅读了another problem,这似乎是因为传递给COM方法的局部变量被垃圾收集,因此VB6运行时遇到了解除分配内存的问题。那个帖子不是这个问题,但它让我思考。

在调用COM的.NET代码中,我们有这种类型的代码

void SomeNETMethod(MyObject obj, bool doIt) {
    string someString = obj.SomeString;
    this.myComComponent.DoItInCOM(ref someString, ref doIt); // This is where it hangs.
}

ref bool以及直接从方法到方法传递参数是否与任何事情有关?正如你所看到的,我在黑暗中磕磕绊绊......

1 个答案:

答案 0 :(得分:0)

查看您的&#34; DoItInCOM&#34;作为内核转储的方法表示正在显示模式对话框(可能是COM方法调用中的错误导致的。)

.NET参数正在被编组到COM端。如果您使用的是某些非标准的C#类型,则可能会遇到序列化问题,但这不是这种情况。

如果您放置&#34; On Error Goto&#34; VB代码中的处理程序可能会抑制会在UI线程上生成消息的错误。如果错误是较低级别(VB运行时正在抛出它),则需要直接修复COM组件的问题。另请查看Windows事件查看器以获取VB Runtime origintatin消息以获取更多信息。