免注册 COM 清单中需要哪些标签? [英] Which tags are required in the manifest for registration free COM?

查看:17
本文介绍了免注册 COM 清单中需要哪些标签?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

TL;DRregsvr32 生成的所有注册表项是否都需要出现在 SxS 无 reg-COM 清单中,反之亦然?

TL;DR Do all registry entries produced by regsvr32 need to be present in a SxS reg-free-COM manifest and vice versa?

我正在尝试为第三方组件获取免注册 COM.

I'm trying to get registration free COM going for a third party component.

阅读 关于主题,我发现有几个元素提到,可以放入清单中:

Reading up on the subject, I find that there are several elements mentioned, that can be put into a manifest:

来自文档,我们可以在清单中添加以下标签来描述 COM 组件:

From the docs, we can add the following tags to a manifest to describe a COM component:

  • assemblyIdentity - 实际上只是描述了抽象 装配" 据我所知
  • comClass - 描述 COM 类(IID 接口).看起来,这总是需要的.
  • typelib - 什么时候?
  • comInterfaceExternalProxyStub - 什么时候?
  • comInterfaceProxyStub - 什么时候?
  • assemblyIdentity - which really just describes the "abstract assembly" as far as I can tell
  • comClass - describes the COM class (IID Interface). It would appear, this is always needed.
  • typelib - when?
  • comInterfaceExternalProxyStub - when?
  • comInterfaceProxyStub - when?

来自其他文档对于 HKEY_LOCAL_MACHINESOFTWAREClasses,我们可以观察到 COM 注册表项有几个类别:

From the other docs for HKEY_LOCAL_MACHINESOFTWAREClasses we can observe that there are a few categories for the COM registry entries:

  • HKEY_LOCAL_MACHINESOFTWAREClassesCLSID{CLSID} I assume roughly corresponds to comClass
  • HKEY_LOCAL_MACHINESOFTWAREClassesInterface{IID} would correspond to either comInterface[External]ProxyStub, but I have seriously no clue when to use which (or both)
  • Which regsitry entry corresponds with the typelib manifest entry ??

使用 regsvr42提取我试图 regfree 的 dll 的东西会产生一个清单,其中只包含 comClass 条目,没有 typelib 或 ProxyStub 条目.(我交叉检查了写的键,有问题的DLL,pdm.dll,MS的进程调试管理器只写那些键,也就是说,注册表中没有明显的类型库或代理存根信息.)

Using regsvr42 to extract the stuff the dll I'm trying to regfree yields a manifest that only contains comClass entries, no typelib or ProxyStub entries. (And I cross checked the keys written, the DLL in question, pdm.dll, MS's Process Debug Manager only writes those keys, that is, there is no type library or proxy stub info apparent in the registry.)

如果注册表仅包含与 comClass 相关的信息,这是否意味着此信息在 SxS 清单中就足够了,或者清单中可能需要其他信息?

If the registry only contains the info that pertains to comClass does this then mean that this info will be sufficient in the SxS manifest, or may additional info be needed in the manifest?

顺便说一句,我注意到注册表包含一个 VersionIndependentProgId 和一个 ProgId,最后附加了一个版本号.清单只有一个 ProgId 条目,文档状态:

As an aside I noticed that the registry contains a VersionIndependentProgId and a ProgId that has a version number appended at the end. The manifest only has a ProgId entry, and the docs state:

progid:与版本相关的程序标识符COM 组件.ProgID 的格式是<vendor>.<component>.<version>.

progid : Version-dependent programmatic identifier associated with the COM component. The format of a ProgID is <vendor>.<component>.<version>.

但文档也说明了

comClass 元素可以将 <progid>...</progid> 元素作为children,列出版本依赖的 progid.

The comClass element can have <progid>...</progid> elements as children, which list the version dependent progids.

他们说 progid 属性应该是与版本无关的.

and they say that the progid attribute should be the version independent one.

那么,这里放什么?当客户不请求特定版本时,这是否重要?

So, what to put here? And does it even matter when the client doesn't request a specific version?

推荐答案

assemblyIdentity 元素始终是必需的,它是清单管道的一部分.您必须始终提供 comClass 元素,它替代 HKLMSoftwareClassesCLSID 注册表项,并用于使客户端的 CoCreateInstance() 调用工作.file 元素命名 COM 服务器可执行文件.

The assemblyIdentity element is always required, part of the manifest plumbing. You must always provide the comClass element, it substitutes the HKLMSoftwareClassesCLSID registry key and is used to make the client's CoCreateInstance() call work. The file element names the COM server executable file.

其余的键是可选的,它们是进行编组工作所必需的.当客户端调用需要在不同的线程上进行时,就会发生编组.当服务器和客户端在不同的进程中时,这将总是发生,对于进程外服务器或服务器在另一台机器上运行时的情况.当 comClass 元素中指定的 ThreadingModel 需要它时,就会发生这种情况.换句话说,当 COM 对象在一个线程上创建但在另一个线程上被调用并且服务器不是线程安全的.

The rest of the keys are optional, they are needed to make marshaling work. Marshaling occurs when the client call needs to be made on a different thread. That will always happen when the server and the client are in different processes, the case for an out-of-process server or when the server runs on another machine. And it can happen when the ThreadingModel specified in the comClass element demands it. In other words, when the COM object was created on one thread but is called on another and the server is not thread-safe.

RPC 实现了编组,但它需要帮助完成一项工作.它需要知道函数的参数是什么,以及返回类型.这样它就可以正确地将它们的值序列化为一个数据包,该数据包可以通过网络传输或传递给另一个进行调用的线程中的代码.这是代理的工作.存根在接收端运行并反序列化参数以构建堆栈帧并进行调用.函数返回值以及通过引用传递的任何参数值然后返回给调用者.否则进行调用的代码根本不知道它没有直接调用该函数.

RPC implements the marshaling but it has one job to do that it needs help with. It needs to know what the arguments for the function are, as well as the return type. So that it can properly serialize their values into a data packet that can be transmitted across a network or passed to the code in another thread that makes the call. This is the job of the proxy. The stub runs at the receiving end and deserializes the arguments to build the stack frame and makes the call. The function return value as well as any argument values passed by reference then travel back to the caller. The code that makes the call otherwise has no awareness at all that it didn't call the function directly.

有四种基本情况:

  • COM 服务器根本不支持以这种方式调用,并且必须始终从创建它的同一线程中使用.到此为止,无需在清单中添加任何内容.

  • The COM server doesn't support being called that way at all and must always be used from the same thread it was created on. Stop there, no need to add anything to the manifest.

COM 服务器实现 IMarshal界面.当 COM 无法找到另一种编组调用的方式时,由 COM 自动查询.这非常罕见,除了 COM 服务器聚合自由线程编组器的情况.换句话说,它本身是完全线程安全的,不需要任何帮助,并且总是在进程中运行.PDM 很可能以这种方式工作.到此为止,无需在清单中添加任何内容.

The COM server implements the IMarshal interface. Automatically queried by COM when it cannot find another way to marshal the call. This is quite rare, except for a case where the COM server aggregates the free-threaded marshaller. In other words, is completely thread-safe by itself without needing any help and always runs in-process. PDM is likely to work that way. Stop there, no need to add anything to the manifest.

COM 服务器作者通过用 IDL 语言编写服务器的接口描述来开始他的项目.然后由 MIDL 编译.它提供的一个选项是从 IDL 声明中自动生成代码,该代码可用于构建实现代理和存根的单独 DLL.IDL 足够丰富来描述函数参数类型和用法的详细信息,以允许通过此自动生成的代码完成编组.有时 IDL 属性是不够的,COM 作者然后编写了一个自定义编组器.COM 在运行时加载该 DLL 以自动创建代理和存根对象.

The COM server author started his project by writing the interface description of the server in the IDL language. Which was then compiled by MIDL. One option it has available is to auto-generate code from the IDL declarations, code that can be used to build a separate DLL that implements the proxy and the stub. IDL is sufficiently rich to describe details of the function argument types and usage to allow the marshaling to be done by this auto-generated code. Sometimes IDL attributes are not sufficient, the COM author then writes a custom marshaller. COM loads that DLL at runtime to create the proxy and stub objects automatically.

特定于 COM 自动化子集(IDispatch 接口),Windows 有一个内置的编组器,它知道如何编组满足子集要求的调用.很普通的.它使用类型库来发现函数声明.

Specific to the COM Automation subset (IDispatch interface), Windows has a built-in marshaller that knows how to marshal calls that meet the subset requirements. Very common. It uses the type library to discover the function declaration.

后两个项目符号需要使用 HKLMSoftwareClassesInterface,它有每个接口的 IID 条目.这就是 COM 找出如何为接口创建代理和存根的方法.如果它找不到密钥,那么它会退回到 IMarshal.您必须使用 comInterfaceExternalProxyStub 元素来替换注册表项.使用 comInterfaceProxyStub 是一种特殊情况,即代理和存根代码包含在 COM 服务器可执行文件中,而不是单独的文件.例如,ATL 项目中的一个选项通过允许合并代理/存根"向导选择打开.

The latter two bullets require using HKLMSoftwareClassesInterface, it has entries for the IID for every interface. That's how COM finds out how to create the proxy and the stub for the interface. If it cannot find the key then it falls back to IMarshal. You must use the comInterfaceExternalProxyStub element to substitute the registry key. Using comInterfaceProxyStub is a special case, that's when the proxy and stub code is included with the COM server executable instead of being a separate file. An option in ATL projects for example, turned on with the "Allow merging of proxy/stub" wizard selection.

最后一个项目符号还需要使用 typelib 元素,这样内置编组器才能找到所需的类型库.

The last bullet also requires using the typelib element, required so the built-in marshaller can find the type library it needs.

COM 客户端通过 IDispatch 使用后期绑定时需要 progId,客户端运行时支持库中的 CreateObject() 辅助函数是样板文件.例如,在任何脚本主机中使用.

The progId is required when the COM client uses late binding through IDispatch, the CreateObject() helper function in the client's runtime support library is boilerplate. Used in any scripting host for example.

了解一些有关如何创建 COM 服务器的内部知识肯定会有所帮助,请始终联系供应商或作者寻求建议.它可以进行逆向工程,但是通过观察注册服务器时写入的注册表项,SysInternals 的 ProcMon 工具是最好的查看方式.要寻找的基本内容:

Having some insider knowledge of how the COM server was created certainly helps, always contact the vendor or author for advice. It can be reverse-engineered however by observing what registry keys are written when the server is registered, SysInternals' ProcMon tool is the best way to see that. Basic things to look for:

  • 如果您看到它编写了 HKLMSoftwareClassesInterface 键,那么您可以假设您必须提供 comInterface|External|ProxyStub 元素

  • If you see it write the HKLMSoftwareClassesInterface key then you can assume that you must provide the comInterface|External|ProxyStub element

如果您看到它为 ProxyStubClsid32 键写入 {00020420-0000-0000-C000-000000000046},那么您可以假设它正在使用标准编组器,并且您必须使用 comInterfaceExternalProxyStub 元素以及 typelib 元素.然后,您还应该看到它写入了 IID 的 TypeLib 注册表项以及 HKLMSoftwareClassesTypelib 注册表项中的条目.后者给出了类型库的路径.几乎总是和 COM 服务器一样,将类型库作为资源嵌入是很常见的.如果它是单独的(一个 .tlb 文件),那么您必须部署它.

If you see it write {00020420-0000-0000-C000-000000000046} for the ProxyStubClsid32 key then you can assume it is using the standard marshaller and you must use comInterfaceExternalProxyStub element as well as the typelib element. You should then also see it write the IID's TypeLib registry key as well as the entry in the HKLMSoftwareClassesTypelib registry key. The latter gives the path of the type library. Almost always the same as the COM server, embedding the type library as a resource is very common. If it is separate (a .tlb file) then you must deploy it.

如果 ProxyStubClsid32 键值是另一个 guid,那么您可以假设它使用自己的代理/存根 DLL.然后您还应该看到它为代理编写了 CLSID 键,它的 InProcServer32 键为您提供了 DLL 的路径.如果该文件名与服务器的文件名匹配,那么您可以假设代理/存根代码已合并,您必须改用 comInterfaceProxyStub 元素.如果没有,则需要 comInterfaceExternalProxyStub,您必须部署 DLL

If the ProxyStubClsid32 key value is another guid then you can assume it is uses its own proxy/stub DLL. You should then also see it write the CLSID key for the proxy, its InProcServer32 key gives you the path to the DLL. If that file name matches the server's file name then you can assume that the proxy/stub code was merged and you must use the comInterfaceProxyStub element instead. If not then comInterfaceExternalProxyStub is required and you must deploy the DLL

如果您看到它在 HKLMSoftwareClasses 中写入 ProgID,则使用 progid 元素,正如跟踪中所示.

If you see it write the ProgID in HKLMSoftwareClasses then use the progid element, exactly as shown in the trace.

这篇关于免注册 COM 清单中需要哪些标签?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆