本文主要介紹 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),但願能對同窗們有所幫助....