使用隔离COM

时间:2015-11-20 23:32:57

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

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

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

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

FSCulture.dll

作为测试,我尝试使用与隔离COM相同的COM服务器创建VB6客户端EXE并遇到了另一个问题。我得到了

  

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

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

  

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

我运行sxstrace来查看正在发生的事情,并且毫不奇怪,它无法找到服务器清单文件,因此它会出错。现在,如果我将服务器清单文件恢复为其原始名称并重新运行客户端,我将重新收到错误ntdll.dll!_ZwDelayExecution@8() Unknown ntdll.dll!__LdrpInitialize@8() Unknown ntdll.dll!_LdrInitializeThunk@8() Unknown 。如果我在这种情况下运行sxstrace,则解析的输出文件为空。

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

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

regasm

服务器清单如下所示:

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

1 个答案:

答案 0 :(得分:0)

尝试在未受管理的客户端和受管服务器之间设置隔离的COM时,存在许多缺陷。其中之一是隔离的COM设置不适用于此场景(我相信它们用于引用未受管理的服务器)。我怀疑另一个问题是,在没有嵌入正确的清单文件的情况下尝试调试此配置会导致在发布模式和调试模式之间产生不同的结果,因为生成清单文件的位置,方式和时间。现在,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对象。