注册免费的Com和dll清单

10
我正在尝试设置无需注册的COM对象,但是我遇到了一个小问题,即另一个COM对象可能是客户端。
应用程序.exe----->COM服务器/客户端dll(已注册或未注册)-------->COM服务器DLL(未注册)
我的问题是,是否可以为第二个dll(COM服务器/客户端dll)创建一个清单文件?我无法控制可执行文件,但如果我能够控制它,那么为可执行文件创建一个客户端清单以及为COM服务器dll创建一个服务器清单将会起作用。
这是中间dll的清单文件。我尝试嵌入它并将其设置为外部,仍然无法正常工作。
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <assemblyIdentity type="win32" 
                    name="COMCliSer.dll" 
                    version="1.0.0.0" 
  />
  <dependency>
    <dependentAssembly>
      <assemblyIdentity 
                     name="COMSer.dll" 
                    version="1.0.0.0"                    
      />
    </dependentAssembly>
  </dependency>
</assembly>
深入调查后,我发现只要中间的动态链接库也是无注册表可用的,并且exe拥有一个应用程序清单,就可以让所有东西都正常工作。但一旦我注册了中间dll,并删除了应用程序清单(我无法控制使用我的dll的exe),整个过程就会停止工作。
如果exe没有清单,那么不会考虑dll的清单。我可以通过设置好一切,然后在程序集清单中放置错误来证明这一点。这将弹出通常的消息:
“无法创建进程:此应用程序无法启动,因为应用程序配置不正确。重新安装应用程序可能会解决此问题。”
如果我删除应用程序清单,应用程序会加载(尽管CoCreateInstance失败,因为依赖项不会被考虑)。

为什么要将程序集称为“comser.dll”?程序集清单信息是否已合并?使用具有描述性名称的程序集(例如“Microsoft.VC90.CRT”)更容易部署,其中包含具有不同名称的dll:“msvcr90.dll”。当处理dll程序集时,调试变得更加困难,因为单个清单现在具有两个目的:向消费者描述程序集的内容,并描述程序集中dll的依赖项。 - Chris Becke
名称已更改以保护无辜者!这些不是真实的名称。这些是本地COM dll,而不是.NET程序集。 - Steve
此外,“不起作用”是指什么呢?exe文件和第二个动态链接库是否加载并且只是无法实例化第三个,还是exe文件或第二个dll完全无法加载?让事情真正失败加载是一个好的步骤,因为这意味着系统至少在系统或应用程序事件日志中看到了清单,并记录了错误。如果仅在调用CoCreateInstance时失败,则可能根本无法看到清单。 - Chris Becke
第二个DLL的CoCreateInstance失败。 - Steve
Steve,你可以发布你的最终解决方案吗?这是一个很棒的问题,我很想看看你是如何实现你的解决方案的。 - WillowDweller
1个回答

5

只需向服务器/客户端dll的清单中添加一个组件依赖项,指向com服务器dll。

请记住,程序集清单与“应用程序”清单不同:程序集清单描述程序集:给它命名,并列出其dll。应用程序清单是嵌入式资源RT_MANIFEST,描述当前模块的依赖关系。

因此,最终结果如下:

  • app.exe,带有外部(app.exe.manifest)或嵌入式RT_MANIFEST,描述对名为“acme.clientserver”的程序集的依赖关系
  • acme.clientserver.manifest描述一个程序集,并将'clisrv.dll'列为无需注册的com dll。
  • clisrv.dll,带有外部(clisrv.dll.2.manifest)或嵌入式RT_MANIFEST,描述对名为“acme.server”的程序集的依赖关系
  • acme.server.manifest描述一个程序集,将serv.dll列为无需注册的com dll。
  • serv.dll - 可能会有清单列出更多的依赖程序集,也可能没有。
技术上可以通过dll的名称调用程序集,并将程序集和dll清单合并在一起,win32加载程序支持这一点,但是应用程序清单中有效的一些设置在程序集清单中无效,这可能导致最终的程序集无法加载。它也使数字签名变得非常困难。
关于exe必须有清单文件的问题:通常,exe的清单文件设置了进程的默认激活上下文。我不确定Windows在exe没有清单文件时会如何处理,但我相信dll中的清单仍然会被处理。
这意味着问题归结为CoCreateInstance缺乏隔离支持 - 出于某种原因,默认情况下,CoCreateInstance仅在默认激活上下文中查找无需注册的COM条目。
覆盖它的方法是手动构建自己的激活上下文,使用Activation Context API
基本方法是调用:
- CreateActCtx - 从您的dll清单创建一个激活上下文。 - ActivateActCtx - 激活上下文 - CoCreateInstance - 现在将在当前激活上下文中搜索无需注册的COM条目。 - DeactivateActCtx - 恢复默认激活上下文。
您可以添加/D ISOLATION_AWARE_ENABLED来包装大多数受激活上下文影响的Windows调用,由于某种原因,CoCreateInstance未被包装 :/

好的,完成了。该dll有两个RT_Manifests,一个我猜是编译器(Delphi)放置的命名为Windows Common Controls的依赖项,另一个则是我添加的,如上所示。 - Steve
哎呀,我对在使用Visual C++时如何合并清单依赖项充满建议。但是对于Delphi,我无能为力:你确实需要将依赖信息与Delphi的合并-至少Delphi是否包含平台SDK中的“mt.exe”工具?MT非常灵活,可以更新嵌入式清单,合并其他清单。 - Chris Becke
所以你的意思是我的问题在于我有两个依赖项。如果我可以合并它们,那么就应该没问题了?我会检查 mt.exe。 - Steve
我在这里取得了一些进展,这就是为什么我接受了答案。请参见问题以获取更多信息。 - Steve
直接使用激活上下文 API 可以解决我所有的问题。谢谢。现在我只需要将程序集清单作为资源嵌入,但说实话,即使我不能那样做,也没关系!谢谢 Chris! - Steve
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接