COM-.NET 互操作漫游






1.64/5 (10投票s)
2007年2月17日
7分钟阅读

47911
这将帮助您理解,我们如何创建可以与 .NET 进行通信的对象,反之亦然。
在 .NET 中使用 COM 组件
引言
本文将帮助您理解 .NET 环境与 COM 组件(它们只是 Win32 动态链接库和 ActiveX 控件)之间的互操作性。
也就是说,.dll 和 .ocx 文件。
背景
设想一下,如果您有几个 COM 组件,包括 DLL 和 ActiveX 组件,现在是时候升级应用程序的功能和 UI 了,同时还需要通过 Web 来提供应用程序。所以,我决定用 .NET 编写部分应用程序,这样就可以消除 Web 部署以及 DLL 和 ActiveX 的注册问题。
在上述场景中,您可以选择完全重写一个纯 .NET Framework 应用程序,或者在新的 Web 应用程序和桌面应用程序中利用现有的业务逻辑功能。是的,我谈论的是 COM-.NET 互操作,这是我们能够与 COM 组件通信,反之亦然的方式。
让我们开始深入探讨,找出 COM 互操作到底是什么,以及实现它的不同方法。
DLL 和 OCX 文件究竟是什么?
动态链接库 (DLL) 是一个代码文件,包含可以从其他可执行代码(应用程序或其他 DLL)调用的函数。程序员使用 DLL 来提供可重用的代码,并随产品一起分发。与可执行文件 (EXE) 不同,DLL 不能直接运行。DLL 必须从其他正在执行的代码调用。
DLL 是一个以 .DLL 扩展名命名的文件。
例如:> kernell32.dll, msvbvm60.dll, msvcrt32.dll
简单来说,DLL 是一个包含可供外部世界调用的函数的文件,外部世界可以利用这些函数调用。这里的外部世界就是指另一个 DLL 或应用程序。
另一方面,OCX 或简称 ActiveX 组件是组件(DLL 和 OCX 合称为 ActiveX 组件)。在下一节中,我们将了解 ActiveX 组件究竟是什么。
ActiveX 组件
ActiveX 控件实际上就是“OLE 对象”的另一种说法,或者更具体地说,“组件对象模型 (COM) 对象”。换句话说,一个控件至少是一个支持 IUnknown 接口并且是自注册的 COM 对象。通过 QueryInterface,容器可以管理控件的生命周期,并根据可用的接口动态发现控件功能的完整范围。这允许控件实现尽可能少的功能,而不是支持大量实际上不做任何事情的接口。总之,仅仅需要 IUnknown 接口和自注册这一最低要求,就可以使任何控件都尽可能轻量级。除了 IUnknown 和自注册之外,对控件没有其他要求。但是,关于支持接口在控件为容器提供的功能方面意味着什么,也应该遵循一些约定。本节将描述控件实际支持接口意味着什么,以及控件在有机会支持方法、属性和事件时应提供的基线。
我认为,这足以说明我们如何以及在何处可以与 .NET 中的 COM 进行交互,反之亦然。
运行时可调用包装器 (Runtime Callable Wrappers)
如背景中所述,.NET 应用程序很可能需要与 COM 进行互操作,我们首先将找出如何实现这一点。 .NET 应用程序通过运行时可调用包装器 (Runtime Callable Wrappers) 或 RCW 来访问 COM。RCW 包装 COM 对象,充当 COM 和 .NET 运行时之间的桥梁,并且就像 RCW 是原生对象一样。
我们可以通过两种方式生成 RCW。第一种,使用 Visual Studio .NET。在 Microsoft Visual Studio .NET 中,右键单击项目中的“引用”部分(如果看不到项目下的“引用”部分,请单击“解决方案资源管理器”窗口中的“显示所有文件”图标,默认情况下,“引用”部分在 Visual Studio 2005 中是隐藏的)。选择“添加引用”,您将看到对话框(图 1),在此您可以浏览要作为引用添加到项目中的 COM 组件。选择所需文件并单击“添加”,Visual Studio .NET 将创建 RCW 并将其作为引用添加到项目中。
(图 1.)
如果您不使用 Microsoft Visual Studio .NET 环境,还有另一种创建 RCW 的方法。安装 .NET Framework SDK (VS.NET) 时,系统会安装一套工具。其中一个工具称为 TlbImp.exe(类型库导入程序实用工具),可用于创建 RCW 或运行时可调用包装器。让我们找出如何实际导入 COM 作为引用,或者如何创建 RCW。
(注意:要运行此示例,请确保您的系统变量已设置库路径。)
例如,如果您想从命令行将 COMDemo.dll COM 组件添加为引用,则在命令行中输入以下内容。
C:\> tlbimp comdemo.dll
它将在您指定的目录中创建 RCW,现在您可以通过导入或创建对象在项目中使用 RCW。
COM 可调用包装器 (COM Callable Wrappers)
另一方面,假设您有一个已经支持 COM 的客户端,现在您想让它使用 .NET 对象而不是。这是一种不太常见的情况,因为它假设在 .NET 世界中进行了新的 COM 开发。但我可以轻松地看到这种情况发生,如果您有一个现有的 COM 客户端使用 10 个 COM 对象,而您现在想添加一个仅以 .NET 对象形式存在的功能集。 .NET Framework 也通过 COM 可调用包装器 (CCW) 支持这种情况。
这里发生的是完全相反的事情。CCW 包装 .NET 对象,使其可用于 COM 交互,它就像一个 COM 组件一样,供 .NET 世界之外的其他 COM 对象或应用程序使用。现在有一些规则需要我们遵循才能使其正常工作。首先,需要公开给 COM 的 .NET 组件必须具有强签名名称,否则 CLR 将无法识别它。其次,它必须驻留在本地计算机的全局程序集缓存 (GAC) 中。如果您希望您的 CCW 对其他应用程序也可用,那么它必须驻留在 GAC 中;如果不是(这种情况较少),那么它必须存在于应用程序目录中(然后它将充当私有程序集,仅可用于该特定应用程序)。实际上,COM 组件不知道在创建对象时如何传递参数,需要公开的 .NET 组件必须有一个默认构造函数(一个不带参数列表的构造函数)。
为了让 COM 组件能够找到 .NET 对象,您还需要为该 .NET 组件进行注册表项。我们可以使用一个名为 RegAsm.exe 的工具来实现这一点,该工具在安装 .NET SDK 时可用。要注册,请在命令行中键入以下内容。
C:\> regasm < .NET 组件的名称 >
注册成功后,COM 组件就可以利用 .NET 对象。
在下一篇文章中,我们将更深入地探讨如何创建用于 COM 交互的 .NET 组件以及如何控制其公开。
这里有一些您可以利用的有用信息。
1) 使用 Win32 命令行注册 DLL、OCX。在“开始”->“运行”中键入以下内容,以注册任何 dll 或 ocx 文件。Regsvr32 "path"\xyz.dll 或 Regsvr32 /i path"\xyz.dll
2) 要从 Windows 注册表中注销已注册的路径,请键入 Regsvr32 /u path"\xyz.dll
[注意:此注册方法仅适用于 COM 组件]