默认情况下COM组件是要在注册表注册的,但是这会引起管理上的问题……

Simplify App Deployment with ClickOnce and Registration-Free COM

全局注册的COM会引起一个叫DLL Hell的问题。

.NET中是通过Global Assembly Cache来管理配装件的

Reg-Free COM看起来在WinXP中就有。需要一个XML宣单(manifest)来记录那些本来需要放在注册表中的信息。这个宣单是给操作系统看的(具体为Native Assembly Loader)。

WindowsApplication1.exe的宣单必须在同一目录,名字为WindowsApplication1.exe.manifest。宣单随应用程序一起加载(CreateProcess的早期),于是在执行前就知道其内容了。操作系统会构建一张表,在CoCreateInstance的时候会优先查询这个表。

VS2005中每个COM引用有一个属性叫做Isolated,默认为False。设为True时支持Reg-Free COM。当VS看见Isolated时,会为其扫描生成manifest。

文章后部讲了一个VB写成的Reg-Free COM的例子。

Registration-free COM

如果不通过CoCreateInstance,那么连Reg-Free COM都不需要的。

  1. 定位到COM组件的DLL
  2. 通过LoadLibrary加载之
  3. 通过GetProcAddress定位到DllGetClassObject
  4. 通过执行DllGetClassObject获得IClassFactory
  5. 通过调用IClassFactory::CreateInstances

简单地说,就是不需要操作系统为你寻找COM组件的接口指针位置。

Enhancing Non-packaged Desktop Apps using Windows Runtime Components

Win10 1903开始支持无封包桌面应用对自定义(第三方)WinRT组件的使用。因为使用自定义组件需要封包标识,无法把组件注册到系统中。此前只支持在有封包应用中使用。

解决额手段时引入Reg-free WinRT,跟Registration-free COM一个慨念。也就是在Win32-style application.manifest,而不是在系统注册表中宣告组件。

这么做的好处之一是可以使用UWP XAML Islands

机制上,在Win32-style application.manifest引入了一个新的activatableClass元素,用于指明WinRT标类。示例如下:

<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>

<file name="WinRTComponent.dll">
<activatableClass
name="WinRTComponent.Class1"
threadingModel="both"
xmlns="urn:schemas-microsoft-com:winrt.v1" />
<activatableClass
name="WinRTComponent.Class2"
threadingModel="both"
xmlns="urn:schemas-microsoft-com:winrt.v1" />
</file>

文中介绍了两个例子:

其他例子:

其他参考

(完)

2022-03-12更新

(更新完0