crocodile's blog

a python lover

Subscribe to RSS feed

Posts tagged with "COM"

OCX和DLL的区别

, ,

一、关于DLL的介绍

DLL,动态链接库,Dynamic Link Library的缩写,是一个包含函数和数据的模块集合,可以被其它应用程序共享的程序模块。DLL作为共享函数库的可执行文件,封装了一个或多个已被编译、链接的函数。多个进程可以同时使用一个 DLL,在内存中共享该 DLL 的一个副本。DLL 还有助于共享数据和资源。 它和可执行文件(.EXE文件)非常类似,他们的区别在于 DLL 中虽然包含了可执行代码却不能单独执行,只能由需要使用它的应用程序来直接或间接调。[1]

通俗的说,在Windows操作系统中,许多应用程序并不是一个完整的可执行文件,它们的正确执行需要调用一些相对独立的动态链接库,即DLL文件。一个应用程序可以调用多个DLL文件,一个DLL文件也可能被几个应用程序所共用,这样的DLL文件被称为共享 DLL 文件。[2]DLL 文件一般被存在C:\Windows\System 目录下,也可能放在应用程序所在的目录或是子目录中。

提到动态链接,先说明一下静态连接。什么是静态连接呢?在程序链接的过程中,需要将编译后的二进制代码链接成目标代码,链接器从静态链接库中获得所有被引用的函数,并将这些被引用的函数同代码一起放到可执行文件中。那么关于 DLL 的静态连接则是指链接器将被引用的库函数的代码复制到调用 DLL 的可执行模块(.dll 文件或 .exe 文件)中。

什么是动态链接呢?动态链接是系统允许可执行模块(.dll 文件或 .exe 文件)在运行程中,只需要包含在定位 DLL 函数的可执行代码所需的信息。换句话说,可执行模块(.dll 文件或 .exe 文件)在运行时加载这些模块(亦即所需的模块映射到调用进程的地址空间)。[3]

那么动态链接和静态连接 相比,优点有哪些呢?

(1)节省内存,减少交换操作。使用动态链接,多个进程可以同时使用一个 DLL,在内存中共享该 DLL 的一个副本。使用静态链接,每个应用程序都包含被引用的库函数的代码,那么Windows 必须在内存中为每个应用程序加载引用的库函数的代码的一个副本。
(2)节省磁盘空间。使用动态链接,在磁盘上仅需要 DLL 的一个副本。使用静态链接,每个应用程序都包含被引用的库函数的代码。
(3)更易于升级。使用动态链接,DLL 中的函数发生变化时,只要函数的参数和返回值没有更改,就不需重新编译或重新链接使用它们的应用程序。使用静态链接,在函数发生变化时,需要重新链接来生成应用程序。
(4)支持多语言程序,只要程序遵循函数的调用约定,用不同编程语言编写的程序就可以调用相同的DLL 函数。
(5)提供扩展 MFC 库类的机制。可以从现有 MFC 类派生类,并将它们放到 MFC 扩展 DLL 中供 MFC应用程序使用。
(6)支持多语言程序,并使国际版本的创建轻松完成。通过将资源放到 DLL 中,创建应用程序的国际版本变得容易得多。可将用于应用程序的每个语言版本的字符串放到单独的 DLL 资源文件中,并使不同的语言版本加载合适的资源。[4]

DLL 中包含下面两类函数的定义:
导出函数:这些函数由可执行模块(.dll 文件或 .exe 文件)调用。
内部函数:这些函数仅从定义它们的 DLL 中调用。DLL 还导出数据。不过,这些数据由相应的函数使用。

可以通过下列方式调用 DLL 中的函数:
加载时动态链接:可执行模块执行显式调用以导出 DLL 函数。为 DLL 创建导入库,然后将 DLL 链接到应用程序。在加载应用程序时,导入库提供加载 DLL 和查找导出的 DLL 函数所需的信息。
运行时动态链接:在运行时加载 DLL 时,可执行模块使用 LoadLibrary 函数或 LoadLibraryEx 函数。可执行模块调用 GetProcAddress 函数以获取导出的 DLL 函数的地址。在链接时,Windows 搜索预安装的一组 DLL,例如性能库 (Kernel32.dll) 和安全库 (User32.dll)。然后,Windows 按以下顺序搜索DLL:
1.当前进程的可执行程序所在的目录。
2.当前目录。
3.Windows 系统目录。(GetSystemDirectory 函数获取 Windows 系统目录的路径。)
4.Windows 目录。(GetWindowsDirectory 函数获取 Windows 目录的路径。)
5.PATH 环境变量中列出的目录。注意:LIBPATH 环境变量不用于搜索。[3]

DLL 有一个特殊的入口点(DllMain 函数),它在附加和分离进程和线程时运行。此行为允许根据需要创建和销毁数据结构。文件扩展名为 .ocx、.cpl 和 .drv 的文件类型也是 DLL,尽管文件扩展名已改变。
您可以通过创建 DLL 实现以下目的:
(1)将程序划分为可按需加载的单独模块。
(2)存储特定于语言或特定于区域的资源。
(3)使您自己的应用程序能够使用核心代码库。
(4)生成进程内 COM 对象或 ActiveX 控件 (OCX)。
(5)将 OLE 对象用作进程内 DLL。这一用法可改进 OLE 链接的性能。
(6)使用控制面板扩展或使用某些类型的驱动程序。 [3]

二、关于以.ocx为后缀名的ActiveX控件

刚才提到过,文件扩展名为 .ocx、.cpl 和 .drv 的文件类型也是 DLL。

现在的ActiveX 控件等价与以前的OLE控件或OCX,一个典型的控件包括设计时和运行时的用户界面,唯一的IDispatch接口定义了控件的属性和方法,唯一的 IConnectionPoint接口定义控件可引发的事件。一个控件可以在容器中运行,所以从运行的角度看它类似与一个DLL。[5]

尽管 ActiveX 和 OLE 都基于组建对象模型(Component Object Model,COM),它们为程序员提供的却是截然不同的服务。COM提供的是低级的对象捆绑机制,该机制支持对象之间的交互通讯。OLE使用COM来提供低级的应用服务,例如采用连接和嵌入机制,支持用户创建复合文档。与之不同,ActiveX提供更精细的结构,用以支持在网络站点上嵌入控件,以及对事件的交互反应。优化ActiveX,目的是为了提高时间和空间效率,而优化OLE,是为了便于终端用户的使用和集成台式系统的应用程序。ActiveX还为Internet技术带来了一些技术上的变革,例如,ActiveX大大减小了代码量(代码量减少了百分之五十到七十),支持更多的提交和异步连接。 [6]

ActiveX的基础是OLE和COM,但是通过MS的各种开发工具可以屏蔽掉COM模型中许多另人费解的技术细节。ActiveX组件技术包括以下一些方面:(1)自动化服务器 (2)自动化控制器 (3)控件 (4)COM对象 (5)文档 (6)容器 。

以.ocx为后缀名的ActiveX控件主要应用在WEB上和Window Forms程序开发上。应用程序使用ActiveX/COM组件来扩展自身的业务逻辑、事务处理和应用服务的范围。

顺便提一下以.ocx为后缀名的ActiveX控件的注册和卸载方法,在“开始”菜单的“运行”输入以下代码完成任务:
regsvr32 path & "\xxx.ocx" '注册
regsvr32 /u path & "\xxx.ocx" '卸载

其中path代表该xxx.ocx所以在的目录的路径。

三、OCX和DLL的区别

以.ocx为后缀名的ActiveX控件是一种比较特殊的DLL,它的基础是OLE和COM,是有交互界面的可视化控件,定义了控件的属性和方法,定义控件可引发的事件的响应。我们通常说的.DLL为后缀名的文件是一个包含函数和数据的模块集合,可以被其它应用程序共享的程序模块。


本文引用:
[1]http://zhouyi2.jblog.cn/120494.shtml
[2]http://www.symood.com/Article/ShowArticle.asp?ArticleID=197
[3]http://www.jr163.org/cup2/54/54294.htm
[4]MSDN:DLL
[5]http://www.blog.edu.cn/user2/eliming/archives/2006/1127399.shtml
[6]http://www.symood.com/Article/ShowArticle.asp?ArticleID=198

读完《COM技术内幕》一书,整理了一个FAQ

FAQ1:什么是COM组件?〖第一章〗
FAQ2:组件不是……?〖第一章〗
FAQ3:什么是接口?〖第二章〗
FAQ4:接口的作用是什么?〖第二章〗
FAQ5:什么是IUnKnown? 〖第三章〗
FAQ6:QueryInterface函数的作用是什么?〖第三章〗
FAQ7:QueryInterface函数的实现规则是什么?〖第三章〗
FAQ8:QueryInterface的样子?〖第三章〗
FAQ9:QueryInterface函数的参数IID是什么?〖第三章〗
FAQ10:何时需要建立一个新的COM组件版本?〖第三章〗

Question:
什么是COM组件?
Answer:
COM组件是以WIN32动态链接库(DLL)或可执行文件(EXE)形式发布的可执行代码组成。
COM组件是遵循COM规范编写的
COM组件是一些小的二进制可执行文件
COM组件可以给应用程序、操作系统以及其他组件提供服务
自定义的COM组件可以在运行时刻同其他组件连接起来构成某个应用程序
COM组件可以动态的插入或卸出应用
COM组件必须是动态链接的
COM组件必须隐藏(封装)其内部实现细节
COM组件必须将其实现的语言隐藏
COM组件必须以二进制的形式发布
COM组件必须可以在不妨碍已有用户的情况下被升级
COM组件可以透明的在网络上被重新分配位置
COM组件按照一种标准的方式来宣布它们的存在
Question:
组件不是……?
Answer:
COM组件不是一种计算机语言
COM组件不是DLL,只是利用DLL来给组件提供动态链接的能力
COM组件不是一个API函数集。
COM组件不是类
Question:
什么是接口?
Answer:
接口就是提供两个不同对象间的一种连接。
计算机程序是通过一组函数而进行连接的,这组函数就是定义了程序中不同部分的接口。
DLL的接口就是它所输出的那些函数。
C++类的接口就是该类的成员函数集。
COM中的接口是一组由组件实现的提供给客户使用的函数。
在COM中接口是一个包含函数指针数组的内存结构,数组元素是一个由组件实现的函数地址。

Question:
接口的作用是什么?
Answer:
有了组件如何将它们连接起来构成某个应用程序,需要用接口。
在COM中接口就是一切,对客户说组件就是接口集,客户只能通过接口和组件打交道。
说明接口可以保护系统免受外界变化的影响。这是封装的体现。
接口实现了使用户使用同样的方式来处理不同的组件。这是多态的体现。

Question:
接口的如何实现?
Answer:
COM接口在C++中是用纯抽象基类实现。
一个COM组件可以支多个接口。
一个C++类可以使用多重继承来实现一个支持多个接口的组件。
组件可以支持任意数目的接口。
接口应该具有不变性。在组件升级时应该不修改原来的接口,而是添加新的接口。
要精心设计实现接口,以使之能够支持各种不同的实现。

Question:
什么是IUnKnown?
Answer:
IUnKnown是一个接口。
所有COM接口都继承IUnKnown。
IUnKnown的定义在WIN32 SDK中的UNKNWN头文件中。
///IUnKnown的定义
interface IUnKnown
{
virtual HRESULT __stdcall QueryInterface(const IID& iid,void **ppv)=0;
virtual ULONG __stdcall AddRef()=0;
virtual ULONG __stdcall Release()=0;
}

Question:
QueryInterface函数的作用是什么?
Answer:
QueryInterface是IUnKnown的成员函数,客户可以通过此函数来查询组件是否支持某个特定的接口。
QueryInterface函数返回一个指向组件支持的接口的指针。
如果QueryInterface函数没有找到组件支持的接口则返回指针是NULL。
QueryInterface函数可以使用if…then…else语句、数组、散列表、树来实现。
QueryInterface函数不能使用case语句,因为QueryInterface函数返回的是一个HRESULT结构而不是一个数。
QueryInterface也是一种无封处理组件版本的机制。这种机制使得组件的新旧不同的版本可以互操作。
Question:
QueryInterface函数的实现规则是什么?
Answer:
QueryInterface返回的IUnKnown指针总是相同。
若客户获得了某个接口,那么它总能获得此接口。
客户可以再次获得已经拥有的接口。
客户可以返回到起始接口。
若能够在某个接口获得某个特定接口,那么从任意接口都将可以获得此接口。
Question:
QueryInterface函数的参数IID是什么?
Answer:
它是一个结构,接口标识符结构。
IID标识了客户所需的接口。
每一个接口都有一个唯一的接口标识符。所以某个与IID相对应的接口绝对不会发生变化。
接口IID决定了COM组件的版本。
不同的接口具有不同的ID,包括不同版本的接口。

Question:
何时需要建立一个新的COM组件版本?
Answer:
当为已有接口指定新的ID时应该是下面的条件至少有一个成立。
接口中函数的数目发生改变时。
接口中函数的顺序发生改变。
接口中某个函数的参数发生改变
接口中某个函数的参数的顺序发生改变
接口中某个函数的参数的类型发生改变
接口中函数的返回值发生改变
接口中函数的返回值类型发生改变
接口中函数的参数的含义发生改变
接口中函数的含义发生改变
简单地说,COM是一种跨应用和语言共享二进制代码的方法。与C++不同,它提倡源代码重用。ATL便是一个很好的例证。源码级重用虽然好,但只能用于C++。它还带来了名字冲突的可能性,更不用说不断拷贝重用代码而导致工程膨胀和臃肿。
Windows使用DLLs在二进制级共享代码。这也是Windows程序运行的关键——重用kernel32.dll, user32.dll等。但DLLs是针对C接口而写的,它们只能被C或理解C调用规范的语言使用。由编程语言来负责实现共享代码,而不是由DLLs本身。这样的话DLLs的使用受到限制。
MFC引入了另外一种MFC扩展DLLs二进制共享机制。但它的使用仍受限制——只能在MFC程序中使用。
COM通过定义二进制标准解决了这些问题,即COM明确指出二进制模块(DLLs和EXEs)必须被编译成与指定的结构匹配。这个标准也确切规定了在内存中如何组织COM对象。COM定义的二进制标准还必须独立于任何编程语言(如C++中的命名修饰)。一旦满足了这些条件,就可以轻松地从任何编程语言中存取这些模块。由编译器负责所产生的二进制代码与标准兼容。这样使后来的人就能更容易地使用这些二进制代码。
在内存中,COM对象的这种标准形式在C++虚函数中偶尔用到,所以这就是为什么许多COM代码使用C++的原因。但是记住,编写模块所用的语言是无关的,因为结果二进制代码为所有语言可用。
此外,COM不是Win32特有的。从理论上讲,它可以被移植到Unix或其它操作系统。但是我好像还从来没有在Windows以外的地方听说过COM。


什么是COM?


  所谓COM(Componet Object Model,组件对象模型),是一种说明如何建立可动态互变组件的规范,此规范提供了为保证能够互操作,客户和组件应遵循的一些二进制和网络标准。通过这种标准将可以在任意两个组件之间进行通信而不用考虑其所处的操作环境是否相同、使用的开发语言是否一致以及是否运行于同一台计算机。
COM的优点?
首先:用户一般希望能够定制所用的应用程序,而组件技术从本质上讲就是可被定制的,因而用户可以用更能满足他们需要的某个组件来替换原来的那个。其次,由于组件是相对应用程序独立的部件,我们可以在不同的程序中使用同一个组件而不会产生任何问题,软件的可重用性将大大的得到增强。第三,随着网络带宽及其重要性的提高,分布式网络应用程序毫无疑问的成为软件市场上越来越重要的买点。组件价构可以使得开发这类应用程序的过程得以简化。
什么是COM+?
COM+并不是COM的简单升级,COM+的底层结构仍然以COM为基础,它几乎包容了COM的所有内容,COM+综合了COM、DCOM和MTS这些技术要素,它把COM组件软件提升到应用层而不再是底层的软件结构,它通过操作系统的各种支持,使组件对象模型建立在应用层上,把所有组件的底层细节留给操作系统,因此,COM+与操作系统的结合更加紧密。
COM+不再局限于COM的组件技术,它更加注重于分布式网络应用的设计和实现。COM+继承了COM几乎全部的优势,同时又避免了COM实现方面的一些不足,把COM、DCOM和MTS的编程模型结合起来,继承了它们的绝大多数特性,在原有的特性上增加了新的功能。


COM+的新的优点?
以下列出COM+的几个主要特性:

COM+不仅继承了COM所有的优点,而且还增加了一些服务,比如队列服务、负载平衡、内存数据库、事件服务等。

   队列服务对于分布式应用非常有意义,特别是在现在网络速度很慢的情况下,这种机制可以保证应用系统能够可靠地运行。在应用系统包含大量节点但服务器又繁忙的情况下,客户应用程序可以把它们的请求放到队列中,当服务器负载比较轻的时候再处理这些请求;

   又如COM+提供了负载平衡服务,它可以实现动态负载平衡,而且COM+应用程序的负载平衡特性并不需要编写代码来支持,客户程序和组件程序都可以按通常的方式实现。获得负载平衡特性并不是用程序设计的方式来实现的,而是通过配置实现分布式应用程序的负载平衡,如上所讲的队列服务,其实也反映了一种负载平衡。

(1) 真正的异步通讯。COM+底层提供了队列组件服务,这使客户和组件有可能在不同的时间点上协同工作,COM+应用无须增加代码就可以获得这样的特性。

(2) 事件服务。新的事件机制使事件源和事件接收方实现事件功能更加灵活,利用系统服务简化了事件模型,避免了COM可连接对象机制的琐碎细节。

(3) 可伸缩性。COM+的可伸缩性来源于多个方面,动态负载平衡以及内存数据库、对象池等系统服务都为COM+的可伸缩性提供了技术基础,COM+的可伸缩性原理上与多层结构的可伸缩特性一致。

(4) 可管理和可配置性。管理和配置是应用系统开发完成后的行为,在软件维护成本不断增加的今天,COM+应用将有助于软件厂商和用户减少这方面的投入。

(5) 易于开发。COM+应用开发的复杂性和难易程度将决定COM+的成功与否,虽然COM+开发模型比以前的COM组件开发更为简化,但真正提高开发效率仍需要借助于一些优秀的开发工具。

COM+标志着Microsoft的组件技术达到了一个新的高度,它不再局限于一台机器上的桌面系统,它把目标指向了更为广阔的企业内部网,甚至Internet国际互连网络。COM+与多层结构模型以及Windows操作系统为企业应用或Web应用提供了一套完整的解决方案。