本文主要介绍 COM 的基础知识,倾向于理论性的理解,面向初学者,浅尝辄止。html
COM 的英文全称是,Component Object Model,中文译为,组件对象模型。它官方的概念是:The Microsoft Component Object Model (COM) is a platform-independent, distributed, object-oriented system for creating binary software components that can interact. 与其说 COM 是 System,更确切的说,应该叫作 Standard。由于它其实是一套公共的 binary 标准,用于规定 software component 的接口的标准。也有人会把 COM 叫作 Common Object Model,但这实际上是一种误传,起源于当初一名微软的工做人员 Mark Ryland[1]!数据库
可是,在长期的使用中,你们口中念叨的 COM 渐渐生出了各类各样的含义,已经不只仅是最初的含义了。这也是为何,对于初学者来讲,理解起来特别费劲。由于总会查到层出不穷,又良莠不齐的含义,让人很疑惑到底哪一个含义才是标准!编程
其实在我 Research 的时候,这些概念也是最头疼的地方。由于对 COM 概念的不了解,因此没法区分在不一样视角,或者不一样角度下的概念。而在 Research 的时候,每每会看到不少不一样的网页,给出各类 COM 的概念。而让人头疼的就是,这些概念都不统一,让人没法理解。甚至开始怀疑,这些网页真的都是说的同一个东西的概念么?这种混乱,就是由于,不一样的网站,在解释 COM 的时候,用的是不一样的角度。而同一个东西,在不一样的角度和情景之下,天然会有不一样的含义。因此,每每 COM 究竟是什么,要因情景而视之!可是,上面列出的几个角度,已足以让咱们对 COM 的概念,构建出一个较为立体的理解了!小程序
要了解 COM 的历史由来,咱们首先要从科技发展的历史开始捋顺下来。先说 Object Oriented 这种概念,其实,这种概念听说是19世纪60年代就有了,是源自于 MIT。可是那个时候 PC 尚未普及,大多数公司使用的都是十分昂贵的大型机,微软尚未成立,这种状况下,天然对软件的需求也是很是基本的,大多数停留在数学计算,文字处理,和军事使用的范围。并且那个时候,CPU 的概念都还没出现,天然电脑也是不可能具有足够的运算能力的。第一个 CPU,是 Intel 在 1971 年,为完成一家日本公司的订单而设计发明的,自此才解锁的计算的巨大潜力,进入了现代计算机的篇章。而 CPU 的发展与成熟,才造就了后来的软件行业。微软也于 1975 年正式成立。同年,IBM 也开始生产 Portable Computers。那时起,微型电脑开始变成潮流。Microsoft BASIC 这种最先期的编程语言,也诞生于 1975年。那时候,绝大多数的微型电脑,虽然系统都不一样,可是几乎都支持 BASIC 这种编程语言。正是这种编程语言,成为了往后微软的基础。1981年,微软首次为 IBM 提供了操做系统,叫作 QDOC,是微软的第一套系统,但倒是买来的,别人研发的系统。1983年,微软研发出了 Lotus Software,是最先期的电子表格软件,这个软件成为了 IBM 电脑上的明星软件,装机必备。后来 1985年 Windows 1 诞生了,同时伴随着 Microsoft Excel 的诞生。自此以后,软件行业开始变得日益繁荣,微软也开启了本身的软件帝国。windows
软件行业变得日益繁荣,可是 Object Oriented 这种思想,还并无发展到必定的高度。那时候,开发个软件或者系统是很是麻烦,很是复杂的。往后,想给软件添加一个功能,或者升级一个功能时,就更麻烦,由于,没办法独立的,去更新,或者改进,某一个特定的功能。若想要添加新功能,须要全盘改动后,再从新进行编译,很是的费时费力。因而人们就开始想办法解决,上面这个问题,而后 Object Oriented Programming(面向对象的编程)的概念就开始兴起。这时,虽然面向对象编程的概念已经兴起,可是,尚未统一的 Framework 或者说是标准,能让不一样软件之间里的 Object 能够互相交流。因而,不一样的软件,就变成了一个个,孤立在大海中的小岛,里面住着一堆 Objects,没法和外界交流。人们想出的解决办法就是,开发一个系统或者体系,在这个体系中,写软件的人只须要制造出,Software Component 就好了。而,这个 Component 就像是,买回来一个,方块形的,电子配件同样,插在咱们本身的电路板上,就能够开始发挥做用。而这些,Software Component 外表上,必须遵循系统中的统一标准,而内部,就随便怎么编程均可以。后来,微软在1993年,开发出了这个标准,这标准就被叫作,Component Object Model (COM)。api
咱们再把 COM 造成先后的,技术发展,掰开来看下。首先,在 1987年,也就是在 Windows 2 发行的时候,Dynamic Data Exchange (DDE) 技术产生了,做为一种进程间通讯手段(Inter-process communication)。在这个技术以前,只支持系统和客户端应用程序之间的通讯,这个通讯,则是经过 Windows Messaging Layer 实现的。而 DDE 技术,则再此基础之上,实现了客户端应用程序之间的通讯,这也就成为了进程间通讯技术的开端。但这时的通讯,还只是停留在 Text conversations 和 Windows messages 的层面上。以后 Antony Williams 分别于 1988年 和 1990年 发表了两篇微软内部文章,分别是 【Object Architecture: Dealing With the Unknown】和【On Inheritance: What It Means and How To Use It】。正是两篇文章奠基了往后 COM 产生的理论基础。以后,1991年,微软在 DDE 的基础上,开发出了第一个 object-based framework(基于对象的框架),叫作 Object Linking and Embedding (OLE),即对象的链接与嵌入。这个技术是同 Word 软件的发行一同发布的,专一于实现 Compound document(复合型文件),就是将 Excel 文件,嵌入到 Word 中。同在 1991年,微软发布了 Visual Basic 1.0 编程语言,并以 dynamic-link library (DLL) 的形式,附带了 Visual Basic Extensions (VBX) 插件。这个插件让使用者,能够经过 Properties and Methods 来操控 objects (对象)。1992年,随着 Windows 3.1 的发布,OLE2 和它本身的 Object Model,也一同发布了。和 OLE1 不一样,OLE2 是在 COM 概念的基础上从新实施的。这时的 COM Application binary interface (ABI),即 COM 应用接口的标准也发生了改变。1994的时候,微软宣布,OLE2 更名为 OLE,今后 OLE 变成了,微软组件技术(Component Technologies)的统称。同年还发布了 OLE Custom Controls (OCXs) ,做为 VBX 的升级版。后来,在1995年,微软发布了 Visual Basic 4.0,开始支持 OCXs,这时微软也开始考如何让 COM 组件能够实现跨语言支持。这就要求,COM 架构下,必需要提供一个一致的接口,以及提供一组能够调用接口内方法的能力。此后,才发展成了咱们现今熟悉的 COM 的含义。在1996年,微软有发现 OCXs 能够应用在浏览器上,因此就把部分 OLE 更名为 Internet "ActiveX",而后,逐渐的,全部的 OLE 都更名叫作 ActiveX 了。同年后期,微软又拓展了 COM 的能力,使得组件对象,拥有了在网络上通讯的的能力。这个技术被称为 DCOM (Distributed COM)。自此便造成了今时今日的 COM 的概念。浏览器
这篇文章中涉及到了很多的历史,以前在学习,近200年的,科技发展历史时,把 Technology Timeline 写在博客里,感兴趣的同窗能够点进去看一下。在那篇博客中,我把微软技术发展的 Timeline,和科技发展的 Timeline 揉合在了一块儿,这样能帮助咱们感受到,技术是在伴随着科技的发展而发展。也能够看到,COM 这种技术理念的产生,是在PC渐渐普及起来,操做系统渐渐成熟,软件需求逐渐提升以后才有的。因此不少事情的发展,每每都是天然而然的,由于有了需求,才会有相应的发展。COM 的产生,从这个角度说,也是一种必然。由于 COM 实际上,就是一种规范,就像行业规范同样,行业过小天然不用规范,而规模大了,需求大了,天然会产生规范,因此 COM 的产生是一种必然结果。而技术的发展,既在推动着科技的发展,也受制于现有科技的边缘。
网络
我的认为,关于 COM,的一切的一切,最后都是为了这个“接口”。由于只有有了“接口”,才算是真正的实现了 Component Object 的理念(或者说,才算是实现了,把 Object 变成 Component 的想法)。由于只有有了“接口”,Component 才能被叫作组件,才能被调用。因此下面简单描述下,几个常见的,围绕着“接口”的概念:
架构
API 中文为,应用程序编程接口;不少时候,都被直接叫作 “接口” (Interface)。“接口”是“操做系统” 或 “程序库”,提供给应用程序的,接入点,让应用程序能调用,系统某一方面的功能。其主要做用是,让开发人员,能够轻松调用这些功能,而不须要了解,到底怎么作到的,和底层代码。可是,API 并非代码,他只是一个接口,或者说只是一个地址。
app
IDL 中文为,接口描述语言。它是一种 Specification language(规范语言)。是用来描述,软件 Component 的 API 的 “规范语言”。与之相比,Programming Language(编程语言)是能够直接运行,用于系统实现的,形式语言。而,“规范语言” 是一般不能直接运行的,而是用于系统分析和设计的,描述语言。而后,这些一段一段的用来描述 Interface 的文字,就被储存在了 IDL 文件中(文件后缀就是 “.idl”)。每一个这样的文件里面都有,一个 header 和一个 body。格式很整齐。
OLE 中文为,对象连接与嵌入。是能让应用程序建立,包含不一样来源的文档,的复合文档技术。OLE 是创建在 COM 理念的基础之上的。COM 是理论框架,而 OLE 是根据这个框架,实施出来的一套技术。正如以前在,PC Mag 杂质上看到的一个副标题,就很好的诠释了这种关系型:"COM-the master plan that lets Windows apps interact through OLE.[2]" 一个比较常见的例子就是,把 Excel 表格,整个插入到 Word 文档中。而这个 Excel Object,就是经过这个 OLE 技术,链接并嵌入(Linking and Embedding)到 Word 中的。但,正如上文所说,后来 OLE 就变成了,微软组件技术(Component Technologies)的统称。而,像这样的一个典型的 OLE 功能(或 OLE 特性),其背后是有一大堆,Interface(接口)做为支持,才得以实现的。
GUID 中文为,全局惟一标识符,也被称为,UUID (Universally Unique Identifier),即,通用惟一识别码。是一个用于标识信息的,128-bit的,标识符;由一组,32位數的,16进制的,数字组成。数字串,的格式为 8-4-4-4-12 的32个字元;大概长成这样:550e8400-e29b-41d4-a716-446655440000。GUID 具备全球惟一性,出现重复的几率几乎为零。因此才叫作,全局惟一标识符。
CLSID 中文为,类标识符。是一个 GUID,可是,是专门用于,标识 COM class object 的。每个 OLE Class,都会有一个与之对应的,全球独一的 CLSID。
ProgID 能够翻译为,程序标识符,或者,编程标识符。一般状况下,每一个 CLSID,都会有对应的 ProgID。例如,ProgID 是 Msxml2.DOMDocument 的字符串;而 CLSID 则长成这个样子 {F9043C85-F6F2-101A-A3C9-08002B2F49FB}。因此 ProgID 的存在,是为了编程的时候,方便调用。
Registry 中文为,注册表。它是一个 hierarchical database (分层的数据库)。用于储存 Windows 系统,或者应用程序的 low-level settings。但并非,全部的应用程序都选择把设置,存在注册表里。Registry 是从 Windows 3.0,推出 OLE 的时候,开始有的。在那以前,应用程序都是把本身的设置信息存在一个后缀为“.ini”的文本文件中的。除了设置以外,全部的 OLE Objects 的 CLSID, 也都储存在这个 Registry 中。感兴趣的同窗能够去 Regedit.exe 中,这个位置(HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID)看下,全部的 CLSID 都长成什么样。而在每一个 CLSID 的“文件夹”中,又都会储存着,这个 Class 的 ProgID 的名字。
阅读到这里的同窗,应该已经对基本的概念有一些了解。那么咱们就再来看下,在实际运行中,Component(组件)究竟是怎么被调用的。就用在 Word 里面插入一张 Bitmap Image 来举例;当咱们在 Word 程序里,点击插入 Object 的时候,Word 会弹出,插入对象的对话框。而后,程序会马上开始扫描,系统的 Registry,看哪些 Object 是可以插入的,而后,把它们都列在你面前,供你选择。当你选中 Bitmap Image 这个对象后,程序会,马上调出他的 ProgID 名字,而后,把这个名字,递给一个叫作 CoCreateInstance 的 OLE Function。再而后,在这个 Function 的内部,就开始了一系列流程。
首先 OLE 会用马上这个 ProgID(或者 CLSID)去找出与它对应的 Regstry 条目。而后,经过注册表里登记的信息,即可以轻易的找到,提供这个“服务”的,应用程序,或者 Component(.exe 或者 .dll)到底住在哪里。一旦找到了,即可以马上调用(Invoke)这个 Component,而后建立出,一个 Bitmap 对象的 Instance(这个Instance,彷佛也叫作 Interface Pointer)。
这和咱们写代码的时候是同样的,在咱们要使用某个模块的功能以前,都是先经过 PorgID 建立一个 Instance(例如,在 VBScript 中,一般是用Set XL = CreateObject("Excel.Application")
这样的语句)。而后经过这个 Instance,和它提供的 Interface(接口),咱们就能够开始调用,这个实例的各类属性和功能了(例如 XL.Workbooks.Open("FilePath")
)。
固然,这个流程中省略了不少的细节,想要了解具体细节的同窗,就去看我“脚注2”中的 Article 吧,这篇文章虽然是1995年的,可是写的很是的好,很是值得阅读,尤为是在学习 COM 的同窗,这篇文章能很好的提高咱们的理解。好吧,这部分就这么多啦。
研究的过程当中发现,COM 相关的东西,真的是博大精深,做为一只小白,也只能是浅尝辄止了。感谢您花时间阅读,小白贡献,语失莫怪。文章中涉及到的历史并无列在这里的参考阅读,而是列在了我另外一篇叫作 Technology Timeline 的博客里,有须要的同窗能够点进去看下 (^_−)☆。
P.S. 为了写完这篇,关于 COM 的小白文章,真的是有一种,跋山涉水,翻山越岭的感受啊 (T^T),但愿能对同窗们有所帮助....