c# - 使用 Isolated COM 时应用程序在 CoCreateInstance 期间挂起

标签 c# c++ .net dll com

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

但是,当我配置 globalsd.dll对于独立的 COM,给它一个 TLB 文件和 FSCulture.DLL 文件名,整个应用程序就在 CoCreateInstance 期间挂起 globalsd.dll ,我不知道它跑到哪里去了。我尝试在 FSCulture.dll 中创建的对象的构造函数中设置断点但它永远不会被击中。这就像我需要调试 Isolated COM 框架的内部结构。调查和解决此问题的最佳方法是什么?

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

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

作为测试,我尝试使用带有独立 COM 的相同 COM 服务器创建 VB6 客户端 EXE,但遇到了不同的问题。我得到了

Run-time error '-2146234304 (80131040)': Automation error

当我重命名服务器 .manifest 文件并重新运行客户端时,我遇到了同样的错误。然后,如果我触摸客户端 list (文件内容没有变化,只是重新保存同一个文件)错误变为:

The application has failed to start because its side-by-side configuration is incorrect. Please see the application event log or use the command-line sxstrace.exe tool for more detail.

我运行 sxstrace 看看发生了什么,毫不奇怪,它找不到服务器 list 文件,所以它出错了。现在,如果我将服务器 list 文件恢复为其原始名称并重新运行客户端,我又会收到错误 80131040 .如果我在这种情况下运行 sxstrace,解析的输出文件是空的。

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

我不明白为什么只触摸 list 文件(不做任何更改)会有任何影响。我也不明白为什么 SXSTrace 在出现 80131040 错误的情况下不输出任何内容。客户端 list 如下所示:

<?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>

服务器 list 如下所示:

<?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++

最佳答案

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

更新:在与 Microsoft 就相关问题进行讨论后发现了有关此问题根本原因的更多详细信息 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 对象。

关于c# - 使用 Isolated COM 时应用程序在 CoCreateInstance 期间挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33837803/

相关文章:

c++ - 通过 OpenGL Assimp 加载的对象有时会反转法线

c++ - 通过 Delphi 访问 Windows API 是否会降低性能?

C# 数据表如何对相似的行进行分组

C# ToTitleCase 和文本格式的日期/时间

c# - 如何使用 .NET Core 解析 MPEG 视频流

c# - 使用 System.Windows.Media.Imaging 合成两个位图

c# - 使用结构作为类型检查基元的包装器的开销?

c# - 向列表中添加多个变量

c# - 这个逻辑可以简化吗?

c# - 在程序之间切换时重绘问题