在 C# 中使用 COM ActiveX DLL 而不引用它
Posted
技术标签:
【中文标题】在 C# 中使用 COM ActiveX DLL 而不引用它【英文标题】:Use COM ActiveX DLL in C# without referencing it 【发布时间】:2020-09-10 19:28:10 【问题描述】:我正在开发一个小型开源项目,该项目使用我无法分发(因此无法引用)的第三方 COM ActiveX Dll。有没有一种简单的方法可以在我的项目中使用这个 DLL 而无需引用它(System.Reflection 程序集似乎不适用于 COM/ActiveX)?还是应该使用 [DllImport] 将其视为非托管 dll ?
谢谢
【问题讨论】:
当你引用 COM 对象时,你只引用了一个 contract(接口、方法、guid 等)。合同通常位于 TypeLib 中(嵌入为资源或外部 .tlb 文件)。在 .NET 中,该合同通常由“Interop.BlahBlahLib.dll”表示。您可以使用此文件(仅 .NET 的合同表示)来交付您的项目,而无需 合同实施(COM 对象本身)。但我不确定这是什么意思?无论如何,没有人能够使用它。注意:如果你不想发送合同本身,没有办法,合同必须以某种方式存在 这就是我的想法,但似乎 COM dll 以某种方式嵌入到我的 dll 中,因为之后,即使我删除了 COM dll,应用程序仍然可以工作,而它显然不应该工作。有没有办法指定不嵌入 COM dll?注意:COM dll 是一个常见的 dll,任何对我的应用感兴趣的人都会在他们的机器上拥有它(否则他们不会寻找这种类型的应用)。 互操作文件/类型可以嵌入到您的程序集中,但不能嵌入 COM 程序集本身。 所以App仍然只能使用Interop文件,不再需要COM了吗? 术语很重要。您的 .NET 应用程序是一个 COM“客户端”,而您使用的 COM 对象是一个“服务器”。服务器未嵌入客户端,如果删除服务器,客户端将无法工作。当您说“COM dll 以某种方式嵌入”和“如果我删除 COM dll,该应用程序仍然有效”时,不确定您真正指的是什么。如果 COM dll 是操作系统的一部分,那么您的问题是什么? 【参考方案1】:有没有一种简单的方法可以在我的项目中使用这个 DLL 而无需引用它(System.Reflection 程序集似乎不适用于 COM/ActiveX)?
没有。
或者我应该将其视为具有 [DllImport] 的非托管 dll 吗?
通常您将DllImport
用于Windows API 等导出功能,但不适用于COM 服务器或ActiveX 组件。
平台调用是一项服务,它使托管代码能够调用在动态链接库 (DLL) 中实现的非托管函数,例如 Windows API 中的函数。它定位并调用导出的函数,并根据需要跨互操作边界编组其参数(整数、字符串、数组、结构等)。
互操作性使您能够保留和利用对非托管代码的现有投资。在公共语言运行时 (CLR) 控制下运行的代码称为托管代码,而在 CLR 之外运行的代码称为非托管代码。 COM、COM+、C++ 组件、ActiveX 组件和 Microsoft Windows API 是非托管代码的示例。
.NET 框架通过平台调用服务、System.Runtime.InteropServices 命名空间、C++ 互操作性和 COM 互操作性 (COM interop) 实现与非托管代码的互操作性。
平台调用依赖元数据来定位导出的函数并在运行时编组它们的参数。下图显示了这个过程。
从 .NET Framework 4 开始,公共语言运行库支持将 COM 类型的类型信息直接嵌入托管程序集中,而不是要求托管程序集从互操作程序集中获取 COM 类型的类型信息。因为嵌入的类型信息仅包括托管程序集实际使用的类型和成员,所以两个托管程序集可能具有相同 COM 类型的非常不同的视图。每个托管程序集都有一个不同的 Type 对象来表示其对 COM 类型的视图。公共语言运行时支持接口、结构、枚举和委托的这些不同视图之间的类型等效。
类型等效意味着从一个托管程序集传递到另一个托管程序集的 COM 对象可以转换为接收程序集中的适当托管类型。
在 MSDN 的 Interoperability (C# Programming Guide) 部分了解更多信息。
【讨论】:
非常感谢这些澄清。为了确保我没有遗漏任何内容,我在上面的评论中添加了一个后续问题。以上是关于在 C# 中使用 COM ActiveX DLL 而不引用它的主要内容,如果未能解决你的问题,请参考以下文章
使用 Javascript ActiveX 对象触发 C# dll
C# .Net 4.0 应用程序中托管的 C++ ActiveX 控件中的 Xml.Serializer 非法强制转换异常