【问题标题】:Application hung during CoCreateInstance when using Isolated COM使用独立 COM 时应用程序在 CoCreateInstance 期间挂起
【发布时间】:2016-02-23 14:20:03
【问题描述】:

当我没有将客户端 DLL (globalsd.dll) 配置为使用独立 COM 访问在运行主可执行文件 (FCMTSYSM.EXE) 之前公开 COM 接口 (FSCulture.dll) 的 .NET 程序集时,我得到一个应用程序异常(访问冲突),因为 CoCreateInstance 在启动期间调用客户端 DLL (globalsd.dll) 的 DLL (syslev0.dll) 静态初始化期间失败(代码继续尝试运行并使用不存在的 COM 对象)。这是我理解并且可以处理的。我需要改进错误处理和/或使用regasm 注册COM 对象和/或为隔离COM 配置globalsd.dll

但是,当我为独立 COM 配置 globalsd.dll 并为其提供 TLB 文件和 FSCulture.DLL 文件名时,整个应用程序在 globalsd.dll 的 CoCreateInstance 期间仅挂起,我无法弄清楚它在哪里徘徊到。我尝试在FSCulture.dll 中创建的对象的构造函数中设置断点,但它永远不会被击中。就像我需要调试独立 COM 框架的内部一样。调查和解决此问题的最佳方法是什么?

从符号服务器加载符号后,调用堆栈可能更有意义,但对我来说仍然不是特别有用:

ntdll.dll!_ZwDelayExecution@8() Unknown
ntdll.dll!__LdrpInitialize@8()  Unknown
ntdll.dll!_LdrInitializeThunk@8()   Unknown

作为测试,我尝试使用具有隔离 COM 的同一 COM 服务器创建 VB6 客户端 EXE,但遇到了不同的问题。我来了

运行时错误“-2146234304 (80131040)”:自动化错误

当我重命名服务器 .manifest 文件并重新运行客户端时,我得到了同样的错误。然后,如果我触摸客户端清单(不更改文件内容,只需重新保存相同的文件)错误更改为:

应用程序无法启动,因为它的并排配置不正确。请查看应用程序事件日志或使用命令行 sxstrace.exe 工具了解更多详细信息。

我运行 sxstrace 来查看发生了什么,毫不奇怪,它找不到服务器清单文件,因此出错了。现在,如果我将服务器清单文件恢复为其原始名称并重新运行客户端,我将返回错误 80131040。如果我在这种情况下运行 sxstrace,解析后的输出文件是空的。

此时如果我运行regasm 注册服务器,我仍然会收到错误80131040。但是如果我重命名客户端清单,客户端测试运行正常。

我不明白为什么只是触摸清单文件(不做任何更改)会产生任何影响。我也不明白为什么在我收到 80131040 错误的情况下 SXSTrace 什么也不输出。客户端清单如下所示:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
   <assemblyIdentity type="win32" name="Project1" version="1.0.0.0" />
   <dependency>
   <dependentAssembly>
   <assemblyIdentity type="win32" name="SoftBrands.FourthShift.FSCulture" version="1.0.0.0" />
   </dependentAssembly>
   </dependency>
</assembly>

服务器清单如下所示:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" 
  manifestVersion="1.0">
<assemblyIdentity type="win32" name="SoftBrands.FourthShift.FSCulture" version="1.0.0.0" />
<clrClass
            clsid="{23D4FF3D-EEDF-4F68-AD65-749958EE3B2A}"
            progid="SoftBrands.FourthShift.FSCulture.FSCulture"
            threadingModel="Both"
            name="SoftBrands.FourthShift.FSCulture.FSCulture" >
</clrClass>
</assembly>

编辑 我意识到在我原来的场景中必须有另一个线程具有更有用的调用堆栈,所以我再次尝试。事实证明是有的。这是主线程上的调用栈:

ntdll.dll!_ZwAlpcSendWaitReceivePort@32()   Unknown
rpcrt4.dll!LRPC_CASSOCIATION::AlpcSendWaitReceivePort(unsigned long,struct _PORT_MESSAGE *,struct _ALPC_MESSAGE_ATTRIBUTES *,struct _PORT_MESSAGE *,unsigned long *,struct _ALPC_MESSAGE_ATTRIBUTES *,union _LARGE_INTEGER *)   Unknown
rpcrt4.dll!LRPC_BASE_CCALL::DoSendReceive(void) Unknown
rpcrt4.dll!LRPC_BASE_CCALL::SendReceive(struct _RPC_MESSAGE *)  Unknown
rpcrt4.dll!_I_RpcSendReceive@4()    Unknown
rpcrt4.dll!_NdrSendReceive@8()  Unknown
rpcrt4.dll!@NdrpSendReceive@4() Unknown
rpcrt4.dll!_NdrClientCall2()    Unknown
ole32.dll!ServerAllocateOXIDAndOIDs(void * hServer, void * phProcess, unsigned __int64 * poxidServer, long fApartment, unsigned long cOids, unsigned __int64 * aOid, unsigned long * pcOidsAllocated, tagOXID_INFO * poxidInfo, tagDUALSTRINGARRAY * pdsaStringBindings, tagDUALSTRINGARRAY * pdsaSecurityBindings, unsigned __int64 * pdwOrBindingsID, tagDUALSTRINGARRAY * * ppdsaOrBindings) Line 246    C
ole32.dll!CRpcResolver::ServerRegisterOXID(tagOXID_INFO & oxidInfo, unsigned __int64 * poxid, unsigned long * pcOidsToAllocate, unsigned __int64 * arNewOidList) Line 1028  C++
ole32.dll!OXIDEntry::RegisterOXIDAndOIDs(unsigned long * pcOids, unsigned __int64 * pOids) Line 1303    C++
ole32.dll!OXIDEntry::AllocOIDs(unsigned long * pcOidsAlloc, unsigned __int64 * pOidsAlloc, unsigned long cOidsReturn, unsigned __int64 * pOidsReturn)   C++
ole32.dll!CComApartment::CallTheResolver() Line 639 C++
ole32.dll!CComApartment::InitRemoting() Line 996    C++
ole32.dll!CComApartment::StartServer() Line 1204    C++
ole32.dll!InitChannelIfNecessary() Line 1021    C++
ole32.dll!CDllHost::GetApartmentToken(unsigned long & hActivator) Line 461  C++
ole32.dll!DoSTMTApartmentCreate(unsigned long & hActivator) Line 211    C++
ole32.dll!CClassCache::GetActivatorFromDllHost(int fSixteenBit, unsigned long dwDllThreadModel, unsigned long * phActivator)    C++
ole32.dll!CClassCache::GetOrCreateApartment(const ACTIVATION_PROPERTIES & ap, DLL_INSTANTIATION_PROPERTIES * pdip, unsigned long * phActivator) Line 4892   C++
ole32.dll!FindOrCreateApartment(const _GUID & Clsid, unsigned long actvflags, DLL_INSTANTIATION_PROPERTIES * pdip, unsigned long * phActivator) Line 2653   C++
ole32.dll!CProcessActivator::GetApartmentActivator(ActivationPropertiesIn * pInActProperties, ISystemActivator * * ppActivator) Line 1214   C++
ole32.dll!CProcessActivator::CCICallback(unsigned long dwContext, IUnknown * pUnkOuter, ActivationPropertiesIn * pActIn, IActivationPropertiesIn * pInActProperties, IActivationPropertiesOut * * ppOutActProperties) Line 1703 C++
ole32.dll!CProcessActivator::AttemptActivation(ActivationPropertiesIn * pActIn, IUnknown * pUnkOuter, IActivationPropertiesIn * pInActProperties, IActivationPropertiesOut * * ppOutActProperties, HRESULT (unsigned long, IUnknown *, ActivationPropertiesIn *, IActivationPropertiesIn *, IActivationPropertiesOut * *) * pfnCtxActCallback, unsigned long dwContext) Line 1630   C++
ole32.dll!CProcessActivator::ActivateByContext(ActivationPropertiesIn * pActIn, IUnknown * pUnkOuter, IActivationPropertiesIn * pInActProperties, IActivationPropertiesOut * * ppOutActProperties, HRESULT (unsigned long, IUnknown *, ActivationPropertiesIn *, IActivationPropertiesIn *, IActivationPropertiesOut * *) * pfnCtxActCallback) Line 1487    C++
ole32.dll!CProcessActivator::CreateInstance(IUnknown * pUnkOuter, IActivationPropertiesIn * pInActProperties, IActivationPropertiesOut * * ppOutActProperties) Line 1377    C++
ole32.dll!ActivationPropertiesIn::DelegateCreateInstance(IUnknown * pUnkOuter, IActivationPropertiesOut * * ppActPropsOut) Line 1917    C++
ole32.dll!CClientContextActivator::CreateInstance(IUnknown * pUnkOuter, IActivationPropertiesIn * pInActProperties, IActivationPropertiesOut * * ppOutActProperties) Line 685   C++
ole32.dll!ActivationPropertiesIn::DelegateCreateInstance(IUnknown * pUnkOuter, IActivationPropertiesOut * * ppActPropsOut) Line 1917    C++
ole32.dll!ICoCreateInstanceEx(const _GUID & Clsid, IUnknown * punkOuter, unsigned long dwClsCtx, _COSERVERINFO * pServerInfo, unsigned long dwCount, unsigned long dwActvFlags, tagMULTI_QI * pResults, ActivationPropertiesIn * pActIn) Line 1334  C++
ole32.dll!CComActivator::DoCreateInstance(const _GUID & Clsid, IUnknown * punkOuter, unsigned long dwClsCtx, _COSERVERINFO * pServerInfo, unsigned long dwCount, tagMULTI_QI * pResults, ActivationPropertiesIn * pActIn) Line 332  C++
ole32.dll!CoCreateInstanceEx(const _GUID & Clsid, IUnknown * punkOuter, unsigned long dwClsCtx, _COSERVERINFO * pServerInfo, unsigned long dwCount, tagMULTI_QI * pResults) Line 157    C++
ole32.dll!CoCreateInstance(const _GUID & rclsid, IUnknown * pUnkOuter, unsigned long dwContext, const _GUID & riid, void * * ppv) Line 110  C++

【问题讨论】:

  • 调用堆栈说什么?
  • 你必须让它有用,启用微软符号服务器。
  • @HansPassant 我找到了另一个调用堆栈,这还有帮助吗?
  • 您犯了一个非常传统的错误,clrClass 条目需要进入客户端清单。目前还不清楚它是如何找到程序集的,请务必清理 GAC 并取消注册程序集。 .NET 程序集及其依赖项必须复制到与客户端 EXE 相同的目录中。当 CLR 检测到版本不匹配时引发 0x80131040,使用 Fuslogvw.exe 进行故障排除
  • @HansPassant 我直接从msdn.microsoft.com/en-us/library/… 的 Microsoft 示例中获取代码——这是错的吗?

标签: c# c++ .net dll com


【解决方案1】:

尝试在非托管客户端和托管服务器之间设置隔离 COM 时存在许多缺陷。其中之一是隔离的 COM 设置不适用于这种情况(我相信它们是用于引用非托管服务器)。我怀疑另一个问题是,在没有嵌入适当的清单文件的情况下尝试调试此配置可能会导致发布模式和调试模式之间出现不同的结果,因为清单文件的生成位置、方式和时间。现在,https://stackoverflow.com/a/34076433/78162 涵盖了修复此问题中的场景的所有答案。

更新:在与微软就相关问题Application hanging during CoCreateInstance of .NET-based COM object进行讨论后发现了有关此问题根本原因的更多详细信息@

也就是说,在创建需要在 DLL 中动态初始化的对象的静态实例时必须小心,因为如果 /clr 编译器开关未应用于源文件,这些对象将在 DllMain 期间运行,并且如果管理 DllMain 可能会导致死锁由于在https://msdn.microsoft.com/en-us/library/ms173266(v=vs.120).aspx 中更详细地记录了加载程序锁,因此代码在其范围内被引用

一个简单的解决方案(我在另一个上下文中再次遇到此问题时使用的解决方案)是将/clr 编译器开关应用于具有对象的静态实例的源文件,该对象的构造函数引用托管代码 COM对象。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-10-13
    • 1970-01-01
    • 2013-07-10
    • 2021-07-07
    • 2010-11-16
    • 1970-01-01
    相关资源
    最近更新 更多