【发布时间】: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 示例中获取代码——这是错的吗?