我只是试图注册 dll。但是 E:Source Code\bin\Interop.HTML2XHTMLLib.dll 已加载。但是找不到 DllRegisterServer 入口点,显示此错误消息。为什么?
Interop .HTML2XHTMLLib.dll 文件不是您要使用 regsvr32 注册的库。它只是托管互操作程序集,生成的 COM 对象可用于您的 .NET 应用程序。您实际上需要为 HTML2XHTMLLib.dll 注册类型库。
为此,您有两种选择:
- 找到包含该库的可再分发包并将其与您的应用程序一起安装。
- 在您的开发系统上,打开 Visual Studio 的“添加引用”对话框。选择 COM 选项卡并搜索库(就像添加引用时所做的那样)。在那里你会找到图书馆的绝对路径。将库复制到客户端系统并使用
regsvr32
.
由于我不知道 HTML2XHTMLLib 的来源,我只能建议那些方法。你应该更喜欢第一个。
既然你已经开始对此进行赏金,我想更详细地介绍一下 COM 和 InterOp。
COM 和 .NET 程序集之间的差异
COM 中有两种类型的服务器:InProc-servers 和 OutProc-servers。InProc (In Process) 是我们通常知道的DLL的服务器。OutProc(Out of Process)服务器是独立的,在它们自己的进程中运行。我们将它们称为EXE可切割文件。
您想使用 InProc 服务器。您的 COM 服务器 ( HTML2XHTMLLib ) 由两部分组成:
- 一个类型库 (
.tlb
),包含有关服务器的元信息,它包含对象及其可访问性。
- 一个库,包含实现所有对象的代码。该库还导出以下静态函数:
类型库也可以是DLL或EXE文件的资源,这样就只有一个文件了。对于 C# 开发人员来说,这似乎有点令人困惑,因为元信息直接编译成 .NET 程序集并可以通过反射访问。
InterOp:.NET 和 COM 之间的包装器
因此,基本上类型库描述了 .NET 反射访问通过 COM 公开的对象所需的一切。但问题是,COM 组件以不同的格式存储:
- 通常它们被直接编译成机器代码:你不能链接一个 .NET 程序集,用AnyCPU对 COM 服务器编译。COM 服务器直接编译为 x86-assembler 或 x86-64-assembler。它们具有固定的指针大小,因此仅与其中一种编译模型兼容。
- COM 定义了内存管理的规则。每个 COM 对象都必须实现
IUnknown
-interface。这个接口定义了三个方法。这些方法AddRef
和Release
用于内存管理目的。每当客户端访问它需要调用的 COM 对象时AddRef
。这将计数器增加一。当客户端不再需要该对象时,它调用Release
而不是删除该对象,从而导致计数器递减。如果指针达到 0,则删除对象本身。这与 .NET 管理内存的方式不同。在 .NET 中,垃圾收集器以不确定的方式访问堆上的每个对象(您无法确定删除对象的确切时间点)并在没有对它的引用时释放该对象。
- COM 定义了身份规则。每当您只想访问对象的基本接口时,都必须调用
QueryInterface
由IUnknown
. 此方法保证在查询特定接口时始终返回相同的指针。这对于 .NET 也可能是正确的(除了您正在重载一些运算符),但 .NET 确保对象标识的方式是不同的。
- COM 定义了对象关系的规则。诸如Aggregation和Containment之类的疯狂东西也存在于 .NET 中,但实现方式不同。
- COM 定义了不同的多线程规则,例如Single Threaded Appartments和Multi Threaded Appartments。这些线程模型定义了对象以不同方式共存时如何交互。在 .NET 中,您必须手动执行每个同步过程。
此列表可能不完整,我也不想进一步详细说明,因为这只是您的问题的附带问题,但是您会看到,.NET 和 COM 之间存在一些很大的差异。为了管理这些差异,两个世界之间存在一个层:COM InterOp。
如果您从 .NET 调用 COM 服务器,则 InterOp 只不过是一个.NET 程序集,它可以在后台完成所有艰苦的工作。它是使用tlbimp.exe工具创建的。每当您从 COM 选项卡引用库时,Visual Studio 通常会为您调用它。结果是您要注册的库:InterOp.Libary.dll。该库重新定义了 COM 服务器的所有类型库,实现了 COM 所需的规则,并为您执行实际调用。然而,它是一个托管的 .NET 库,它没有定义前面描述的方法。这就是为什么regsvr32
找不到DllRegisterServer
入口点的原因。
上面描述的方式只是一种使用非托管 COM 服务器和托管 .NET 客户端的方式。还有另一种方式,对应的tlbexp.exe和regasm
.