Component_Object_Model

**元件物件模型**（英語：**C**omponent **O**bject **M**odel，縮寫 **COM**）是微軟的一套軟體元件的二進位介面標準。這使得跨程式語言的行程間通訊、動態物件建立成為可能。COM 是多項微軟技術與框架的基礎，包括 OLE、OLE 自動化、ActiveX、COM+、DCOM、Windows shell、DirectX、Windows Runtime。COM 與實作語言種類無關，如此使用它實作的物件可用在不同於開發它的環境，甚至跨越機器邊界。對製作良好的物件，COM 使物件得以重複使用，而無須知道其內部實作，因為它強制實作者提供與實作分離、確切定義的介面。各語言不同的儲存組態語意使元件物件模型用物件參照計數 (Reference counting) 管理其自身的產生與銷毀。不同介面間型別轉換的鑄型用 QueryInterface 方法。

## 概要

COM 的核心是一組元件物件間互動的規範，定義了元件物件如何與其使用者通過二進位介面標準進行互動，COM 的介面是元件的類型紐帶。

除了規範之外，COM 還是一個稱為「COM 媒體櫃」的實現，包括若干 API 函式，用於 COM 程式的建立與使用。

COM 還提供定位服務的實現，可以根據 Windows 系統登錄檔，從一個類標識（CLSID）來確定元件的位置。

COM 採用自己的 IDL 來描述元件的介面（interface），支援多介面，解決版本相容問題。COM 為所有元件定義了一個共同的父介面 IUnknown。GUID 是一個 128 位整數（16 位元組），COM 將其用於電腦和網路的唯一識別碼。

除了基本規範和系統實現之外，COM 的構成還包括永久儲存、綽號（moniker 智慧型命名 / 標記）和統一資料轉移（UDT = Uniform Data Transfer）三個核心的作業系統部件。

COM 實質上是一種語言無關的物件實現方式，這使其可以在建立環境不同的場合、甚至跨電腦的分布環境下被復用。COM 允許復用這些物件，而不必知道物件內部是如何實現，因為元件實現者必須提供良好定義的介面從而封鎖實現細節。通過參照計數，元件物件自己負責動態建立與銷毀，從而封鎖了不同程式語言之間的記憶體分配語意差異。在 COM 介面之間的類型轉換通過 QueryInterface 方法。

對於某些應用程式來說，COM 已經部份被.NET 框架取代。COM 通過 Windows Communication Foundation（WCF）支援 Web Service。COM 物件通過.NET COM Interop 可以被所有.NET 語言使用。網路化的 DCOM 使用二進位私有格式，而 WCF 鼓勵使用基於 XML 的 SOAP 訊息機制。COM 非常類似其他軟體元件介面技術，如 CORBA 與 JavaBeans，它們各自有其優點與弱點。

與 C++ 不同，COM 提供了一個穩定的套用二進位介面（ABI），不隨編譯器版本而改變 。

## 歷史

早在 1988 年，微軟的 Anthony Williams 的論文「Object Architecture: Dealing with the Unknown or Type Safety in a Dynamically Extensible Class」以及 1990 年的「On Inheritance: What It Means and How To Use it」論文奠定了 COM 的理論基礎。

Windows 作業系統提供了三種處理程序間的通訊機制：剪貼簿、DDE 與 OLE。OLE 原名是物件連結與嵌入（Object Linking and Embedding），OLE 可以說是 DDE 的改良版。1992 年，OLE 1.0 版隨 Windows 3.1 作業系統發布，提供複合文件（compound document）處理，但它過於複雜，Brockschmidt, Kraig 的「Inside OLE」一書中提到，必須經過六個月的心靈混沌期，才能了解 OLE 是什麼。1993 年，COM 架構隨 OLE 2.0 第一次公開發布。在微軟 Office 套件中，COM 取代了 OLE。這成為 COM 技術戰勝 Windows 95 團隊開發的其他物件技術的關鍵因素。

1996 年，為應對 CORBA，**DCOM** 隨 Windows NT 4 Option Pack 發布。

1999 年，Windows 2000 發布了 **COM+**，關注 MTS，並放棄了 DCOM 這個名稱。

## COM 元件類型

COM 是基於元件物件方式概念來設計的，在基礎中，至少要讓每個元件都可以支援二個功能：

* 查詢元件中有哪些介面
* 讓元件做自我生命管理，此概念的實踐即為參照計數（Reference Counting）

這二個功能即為 COM 的根：`IUnknown` 介面所提供的 `IUnknown::QueryInterface()`，`IUnknown::AddRef()` 及 `IUnknown::Release()` 三個方法的由來。所有的 COM 元件都要實作 `IUnknown`，表示每個 COM 元件都有相同的能力。

只由 COM 衍生實作出來的元件，稱為**純 COM 元件**。

但在 Windows 持續發展時，Visual Basic 4.0 開始支援 OCX，也就是 OLE Custom Control，這讓微軟開始思考要如何讓 COM 元件可以跨語言支援，在這樣的要求下，必須要提供一個一致的介面，以及提供一組可以呼叫介面內方法的能力，由於純 COM 元件只能夠支援 C/C++ 的直接存取，為了要達到跨語言的能力，在 COM 中必須要支援在外部呼叫內部方法的機能，這個機能造就了 `Invoke()` 方法，另外為了跨語言的支援，COM 應該要提供簡單的元件存取識別方式，這也就是會有 `GetIDsOfNames()` 的原因，將這些方法組合起來，定義出的必要介面，稱為 `IDispatch` 介面，所有實作此介面的，都可以支援跨語言的支援。

微軟將實作此介面的元件都稱為**自動化（Automation）** 元件。

## 相關技術

COM 曾是 Windows 平台下主要的軟體開發平台，並且影響至其他許多相關軟體技術。

### COM+

COM + 是微軟 Windows 2000 中，Microsoft Transaction Server 的強化實作版本，除了提供基本的元件交易支援外，還提供了鬆散藕合式事件（loosely-coupled events）與物件共享池（object pooling）等應用程式伺服器的能力，成為 Windows 2000 開始在微軟平台上主要的應用程式伺服器平台，目前.NET Framework 也提供了 System.EnterpriseServices 命名空間以支援 COM+。

### Distributed COM

Distributed COM 是依據遠程過程調用（RPC，Remote Procedure Call）的規範發展的可以在網路上通訊的 COM 元件，它將 COM 元件的能力擴及到網路上，但因為網路安全以及防火牆因素，DCOM 無法廣泛的流行。

### .NET

.NET Framework 是新一代的 Microsoft Windows 應用程式開發平台。使用 C# 開發 COM 組件，首先建立類型為 Class Library 的專案，然後在專案的 Property 中進入 Build 頁，對「Register for COM interop」選項打勾。打開 AssemblyInfo.cs 檔案，設定 [assembly: ComVisible (true)]，這樣就可以生成.tlb 檔案。源程式範例如下：

### ATL

### WTL

## 技術細節

不同的 COM 元件類型用類 ID（CLSID）標示，這是一種全域唯一識別碼（GUID）。每個 COM 元件用一個或多個介面來暴露其功能。這些介面也採用 GUID 唯一標識，稱為介面 ID（IID）。

COM 介面與幾種程式語言有語言繫結，如 C 語言、C++、Visual Basic、Delphi 語言、Python 以及 Windows 平台上的幾種手稿語言。它們都是通過介面的方法來存取元件。

### 介面

所有 COM 元件都實現了 IUnknown 介面，該介面暴露了參照計數實現的物件生命期管理與類型轉換，以存取不同的預定義介面。

IUnknown 介面以及基於 IUnknown 的客製化介面包括一個指向虛擬函式表的指標，虛擬函式表中包含若干函式指標，分別指向介面所聲明的函式實現。對於處理程序內的 COM 元件呼叫，其效率等同於 C++ 的虛擬函式呼叫。

除了基於 IUnknown 的客製化介面，COM 也支援繼承自 IDispatch 的 dispatch 介面，從而支援了用於 OLE 自動化的晚繫結。不能存取客製化介面的程式語言（例如 VBS）可以通過 dispatch 介面存取 COM 元件。

Windows API 提供了 C 語言定義 COM 介面的方法：

### 類

COM 類（coclass）是一個或多個介面的具體實現，它很類似物件導向程式設計語言中的類。類的 GUID 標識被稱作類 ID（CLSID）；或者 programmatic identifier 字串（progid），因為 VBS 等手稿語言不能使用 GUID，只能用字串尋找、使用 COM 元件。

COM 物件不能被直接存取，只能通過 COM 介面來存取物件。COM 也支援同一個介面的多個實現，因此客戶程式執行時可以選擇實例化介面的哪個實現。

### 介面定義語言與類型媒體櫃

類型媒體櫃（type library）包含著 COM 類型的元資料。這些類型採用微軟介面定義語言（MIDL）描述。

IDL 檔案定義了類、介面、結構、列舉與其他使用者定義類型。IDL 類似於 C++ 的聲明，使用了一些額外的關鍵字如 interface、library 等。IDL 還支援在聲明前給出方括號內容（bracketed attribute）以提供額外資訊，如介面的 GUID、指標參數與長度域之間的關係等。

MIDL 編譯器用來編譯 IDL 檔案，產生編譯器獨立的標頭檔。標頭檔包含了 IDL 檔案中聲明的介面對應的結構定義。結構只包含一項成員，即指向在介面中聲明函式的位址表的指標（vtbl），以模仿 C++ 對虛擬函式的實現。標頭檔還包含了類與介面等的 GUID 的常數的定義。MIDL 編譯器也可以產生 C++ 原始檔，包含代理模組（proxy module），用以把 COM 呼叫轉為遠端程序呼叫，以支援跨處理程序的 DCOM 通信。

IDL 檔案也可以被 MIDL 編譯器生成類型媒體櫃（TLB）檔案 `.TLB`，以供其他語言編譯器與執行時環境使用，如 VB、Delphi、.NET 等生成語言相關表示 COM 類型的結構。C++ 把 TLB 轉回到 IDL 表示。

#### #import 類型資訊

使用 C++ 的預編譯 directive`#import` ，可以裝入如下格式的類型資訊：

* 包含類型媒體櫃的檔案，如.olb、.tlb、.dll 等；
* progid
* libid
* exe 檔案
* dll 檔案包含著類別館資源（如.ocx）
* 複合文件包含了類別館
* 其他可以被 LoadTypeLib 函式理解的檔案

`#import` 建立兩個標頭檔以用 C++ 原始碼形式恢復類型媒體櫃資訊：

* 類型媒體櫃主標頭檔（.TLH）：類似於 MIDL 編譯器產生的標頭檔，還有一些額外的程式碼與資料；
* 類型媒體櫃次標頭檔（.TLI）：編譯器產生的成員函式。該檔案被包含在主標頭檔中。

兩個檔案被放在輸出目錄中。編譯器在現場就地 `#include` 主標頭檔。

類型媒體櫃主標頭檔（.TLH）包含七部份：

* 頭部常規程式碼
* 將要用到的結構的前向參照與 typedef
* 智慧型指標聲明：使用宏語句 \_COM\_SMARTPTR\_TYPEDEF 建立了 COM 介面的 typedef，實際上是 `_com_ptr_t` 的範本特化。
* Typeinfo 聲明：類別定義、ITypeLib:GetTypeInfo 返回的其他 Typeinfo 項
* 可選的舊格式的 GUID 常數定義，形如 CLSID\_CoClass、IID\_Interface
* `#include` 類型媒體櫃次標頭檔
* 尾部常規程式碼：`#pragma pack(pop)`

從第 2 至第 6 部份都包含在命名空間中，其名字在最初的 IDL 檔案的 `library` 語句中給出。改名字在 `#import` 語句中可用內容 no\_namespace 抑制掉；也可用 rename\_namespace 內容更名。

### COM 作為物件框架

COM 是一個執行時框架，類型必須在執行時單獨地標識並可指定。為此，使用 GUID，每個 COM 類型被指定了它自己的 GUID 用於執行時標識。這也解決了 C/C++ 語言的名字修飾導致的連結相容性問題。

為了使 COM 類型資訊在編譯時與執行時都可以存取，COM 使用類型媒體櫃。這使得 COM 成為物件互動的動態框架。

考慮下述用 IDL 定義 coclass 的例子：

上述程式碼框架聲明了一個 COM 類，稱為 `SomeClass`，實現了介面 `ISomeInterface`。

這在概念是等價於下述 C++ 類別：

其中 ISomeInterface 是一個 C++ 虛基礎類別。

包含 COM 介面與類的 IDL 檔案被編譯為類型媒體櫃（TLB）檔案。客戶程式可以在執行時分析類型媒體櫃檔案，以確定物件支援哪些介面，然後呼叫物件的介面方法。

C/C++ 程式以類 ID（CLSID）與介面 ID（IID）作為參數，用 `CoCreateInstance` 函式實例化 COM 物件。`SomeClass` 的實例化程式碼如下：

在這個例子中，使用 COM 子系統取得指向 `ISomeInterface` 介面的實現物件的指標，用 CLSID\_SomeClass 指示用這個特定的 coclass。

### 參照計數

所有 COM 物件採用參照計數管理物件的生命期。客戶程式通過所有 COM 物件都要強制實現的 IUnknown 介面的 AddRef 與 Release 方法來控制參照計數。當參照計數降到 0 時，COM 物件自己負責釋放記憶體。即對動態分配記憶體建立的 COM 物件，其 Release 函式內部參照計數降為 0 時，就釋放自身所占的動態分配記憶體。有的 COM 物件（如 IClassFactory）往往是靜態物件，Release 函式內部參照計數降為 0 時不需做額外的操作。

特定語言（例如 Visual Basic）提供了自動參照計數，所以 COM 物件開發者在原始碼中不需要顯式維護任何內部的參照計數。C/C++ 編程者或者執行顯式的參照計數，或者使用智慧型指標（如 MFC 提供的 CComPtr）自動管理參照計數。

下述是如何呼叫 COM 物件的 AddRef 與 Release 的指引：

* 函式、方法返回介面的參照（通過返回值或者 "out" 參數），應當在返回前增加被返回的物件的參照計數。
* 介面指標被覆蓋或超出作用域之前，必須呼叫介面指標的 Release 方法。
* 如果一個介面參照指標被複製，必須呼叫該指標的 AddRef 方法。
* AddRef 與 Release 必須在被參照的相關介面上呼叫。因為一個 COM 物件可能實現了逐個介面上的參照計數，使得僅在相關介面上內部份配資源。

不向遠端物件發出參照計數的呼叫。代理模組保持著遠端物件的一個參照，並維持著它自己的本機參照計數。

為簡化 COM 開發，引入了活動範本媒體櫃（Active Template Library，ATL）用於 C++ 開發。ATL 提供了更高層次的 COM 開發範式。ATL 也有益於 COM 客戶應用程式開發擺脫直接維護參照計數，而是用智慧型指標物件。

其他能直接支援 COM 的媒體櫃與語言還包括 MFC Visual C++ 編譯器的 COM 支援、VBScript、Visual Basic、ECMAScript（JavaScript）和 Borland Delphi 等。

### 程式設計

COM 是一個語言獨立的二進位標準，任何能夠理解與實現 COM 的二進位定義的資料類型與介面的語言都可以開發 COM 元件。

COM 實現負責進入、離開 COM 環境，實例化與參照計數 COM 物件，查詢物件支援的介面，以及錯誤處理。

Microsoft Visual C++ 編譯器支援對 C++ 語言的擴充：稱作 _C++ Attributes_。這些擴充被設計用於簡化 COM 開發，去除實現 COM 伺服器時大量臃腫的程式碼。

### 使用登錄檔

在 Windows 作業系統中，COM 類、介面、類型媒體櫃都會根據其 GUID 登記到 Windows 登錄檔。HKEY\_CLASSES\_ROOT\CLSID 下是 COM 類；HKEY\_CLASSES\_ROOT\Interface 下是介面。COM 類型媒體櫃註冊在每個 COM 物件的本機媒體櫃條目下或者遠端服務的網路位置處。

### 不使用登錄檔的 COM

不使用登錄檔的 COM（RegFree COM）是 Windows XP 引入的技術，允許 COM 元件不在登錄檔中存期啟用的元資料與類 ID（CLSID），而是在實現類的 assembly manifest 或者儲存在可執行檔的資源中或元件安裝時的單獨檔案中。這使得同一元件的不同版本可以安裝在不同目錄下，用其各自的 manifest 描述，直接複製安裝。這種技術有限支援 EXE COM 伺服器且不能用於系統範圍元件如 MDAC、MSXML、DirectX 或 Internet Explorer。

應用程式裝入時，Windows 裝入器搜尋 manifest。如果存在，裝入器從它增加資訊到啟用上下文。COM 類工廠試圖實例化一個類時，啟用上下文首先檢查這個 CLSID 的實現是否可以找到。僅當尋找失敗時，才掃描 Windows 登錄檔。

### 處理程序與網路透明

COM 物件可以透明地實例化與參照在同一處理程序、跨處理程序邊界、甚至在網上遠端（DCOM）。處理程序外或遠端物件用 marshalling 序列化方法呼叫與返回值。這種 marshalling 對使用者是不可見的，就如同存取處理程序內的 COM 物件。

### 執行緒化與「套間」

一個處理程序載入了一個 COM 的 DLL 檔案後，該 DLL 可能定義並使用了一些可修改的全域變數或存取共享資源。該處理程序內的多個執行緒如何並行存取該 DLL 並保證是執行緒安全的，這就是「套間」（apartment）技術需要解決的問題。

COM 物件與建立或呼叫 COM 物件的執行緒可以按兩種策略來實現並行安全：

* 按照單執行緒執行方式寫 COM 物件的程式碼，完全不考慮並行執行問題。這樣的每個 COM 物件只能由一個執行緒執行，該執行緒通過 Windows 訊息佇列實現多執行緒存取該 COM 物件被串行化從而並行安全。這種策略稱作單執行緒套間（Single-Threaded Apartment，STA）。
* COM 物件的程式碼自身實現了並行控制（通過 Windows 互斥原語，如互斥鎖、臨界區、事件、號誌等）。因此實際上多執行緒可以直接呼叫該 COM 物件的方法，這是並行安全的。這種策略稱作多執行緒套間（Multi-Threaded Apartment，MTA）。

COM 的並行安全的具體實現，提出了套間（apartment）概念。每一種套間類型表示在一個處理程序內部是多執行緒情況下，如何同步對 COM 物件的呼叫。套間是一個邏輯容器，收納遵循相同執行緒存取規則的 COM 物件與 **COM 執行緒**（建立了 COM 物件的執行緒或者呼叫了 COM 物件的方法的執行緒）。套間本質上只是一個邏輯概念而非物理實體，沒有控制代碼類型可以參照它，更沒有可呼叫的 API 操縱它。套間有兩種：

* 單執行緒套間（Single-Threaded Apartment，STA）：每個處理程序可以有多個 STA 套間。每個 STA 套間只能有一個執行緒。每個 STA 性質的 COM 物件只能屬於一個 STA 套間。一個 STA 套間可以有零個或多個 STA 內容的 COM 物件，這些 COM 物件的方法只能由該套間的唯一執行緒執行。STA 套間的執行緒可以直接呼叫該套間的 COM 物件的方法。如果 STA 套間的 COM 物件被套間外的執行緒或處理程序呼叫，那麼該套間的執行緒必須實現 Windows 訊息佇列與訊息迴圈處理機制，其他執行緒必須通過 marshalling 與 unmarshalling 機制，通過給該 STA 套間的執行緒傳送 Windows 訊息來呼叫 COM 物件。每個 STA 性質的執行緒自動形成一個 STA 套間，這個套間容納了該執行緒及其建立的所有 STA 性質 COM 物件。MTA 性質的執行緒建立 STA 性質的 COM 物件時，系統自動把該 COM 物件放在 default STA 套間內，由該套間的 STA 執行緒來執行該 COM 物件的方法。每個處理程序至多有一個 default STA 套間，該套間與套間內執行緒是自動生成的。
* 多執行緒套間（Multi-Threaded Apartment，MTA）：每個處理程序至多有一個 MTA 套間。所有 MTA 性質的執行緒都屬於 MTA 套間。所有 MTA 性質的 COM 物件也都屬於這個 MTA 套間。STA 性質的執行緒建立 MTA 性質的 COM 物件時，系統自動建立一些執行緒以執行這些 MTA 性質的 COM 物件，這些執行緒也屬於 MTA 套間，系統返回安整後的 COM 物件的描述給 STA 性質的執行緒。
* 中立套間（Thread Neutral Apartment，NA）：一個處理程序可以有一個中立套間。中立套間只包含 COM 物件，不包含執行緒。當 STA 或 MTA 執行緒呼叫同一處理程序的 NA 物件，則呼叫執行緒臨時離開它的套間並執行 COM 物件的程式碼，沒有任何執行緒切換。即任何執行緒都可以直接了當呼叫 COM 物件的方法。因此 NA 可以認為是最佳化套間之間方法呼叫的效率。

一個 COM 物件只能存在於一個套間。COM 物件一經建立就確定所屬套間，並且直到銷毀它一直存在於這個套間。COM 物件的套間類型寫在 Windows 登錄檔相關條目中。

一個 COM 執行緒從建立到結束都屬於同一個套間。COM 執行緒只有兩種套間模式：STA 或 MTA。執行緒必須通過呼叫 CoInitializeEx () 函式並且設定參數為 COINIT\_APARTMENTTHREADED 或者 COINIT\_MULTITHREADED，來指明該執行緒的套間模式。呼叫了 CoInitializeEx () 函式的執行緒即已進入套間，直到執行緒呼叫 CoUninitialize () 函式或者自身終止，才會離開套間。COM 為每個 STA 的執行緒自動建立了一個隱藏視窗，其 Windows class 是 "OleMainThreadWndClass" 。跨套間呼叫這個 STA 套間內的 COM 物件，實際上是向這個隱藏視窗傳送了一條視窗訊息，通過訊息迴圈與分派，該視窗過程收到這條視窗訊息並呼叫相應的 COM 物件的介面方法。

執行緒存取屬於同一套間的 COM 物件，直接執行方法呼叫而不需 COM 設施的輔助。執行緒跨套間邊界去呼叫 COM 物件，傳遞的指標需要 marshalling。如果通過標準的 COM 的 API 來呼叫，可以自動完成安整。例如，把一個 COM 介面指標作為參數傳遞給另外一個套間的 COM 物件的 proxy 的情形。但如果軟體編程者跨套間傳遞介面指標而沒有使用標準 COM 機制，就需要手工完成安整（通過 CoMarshalInterThreadInterfaceInStream 函式）與反安整（通過 CoGetInterfaceAndReleaseStream 函式取得 COM 介面的 proxy）。例如，把 COM 介面指標作為執行緒啟動時的參數傳遞的情形。

跨處理程序的呼叫 COM 物件類似於同一處理程序內跨套間的呼叫 COM 物件。

COM 物件 coclass 在登錄檔表示中的子鍵 InProcServer32 下的條目中 ThreadingModel 給出：

## 批評

### 訊息泵

STA 初始化時，建立一個隱藏視窗，用於 apartment 之間、行程間的訊息路由。該視窗必須有正常的訊息佇列泵。這種結構稱為訊息泵。早期版本的 Windows，訊息泵的失敗會導致系統範圍的死結。這個問題被初始化 COM 的 Windows API 複雜化了，並會導致實現細節的泄露。

### 參照計數

如果多個物件是迴圈參照，則可能會導致問題。

Objects may also be left with active reference counts if the 
使用 COM 事件池（event sink）模型，則物件可能一直保持活動的參照計數而不能被銷毀。因為傳送事件的物件必須有處理事件的物件的參照，因而物件參照計數永遠不為 0.

參照迴圈可以採取下述技術來克服：

* 帶外終止（out-of-band termination），物件暴露一個方法，該方法呼叫時迫使該物件放棄對其他物件的全部參照。
* 身分分離（split identity）技術，一個實現暴露兩個單獨的 COM 物件（也稱作 identity），之間保持 weak reference。

### DLL 地獄

處理程序內的 COM 元件是用 DLL 檔案實現，每個版本的 DLL 用 CLSID 登記到 Windows 登錄檔，因而某些情況下會發生 DLL Hell 效應。無需註冊的 COM 克服了這一問題。

### 元件間的約定的表示

COM 元件間的約定，純粹是通過使用者與元件之間的語意保證和假設的形式來表示的。COM 用類型的形式表示元件約定。但是該約定存在如下兩個關鍵問題，使得其對語意的表示並不是最佳的。

* 約定的描述：COM 沒有定義約定的交換格式，即 COM 規範所約定的類型定義，必須通過完全是 COM 之外的某種技術來進行互動。微軟定義和支援的 COM 交換格式有兩個 ——IDL（Interface Definition Language 介面語言定義）和 TLB（Type LiBrary 類型媒體櫃），但是這兩種格式並不是同構的，其中也沒有哪種格式是權威的或標準的。
  * COM 缺乏對元件依賴性的描述。因此，沒有辦法來解析 COM 元件（或者其約定的定義），也不能確定它所需要（依賴）的其他元件與版本。
  * COM 約定的描述格式缺乏擴充性。IDL 是基於文字的，極少隨元件部署，通常只有 C++ 程式設計師才會使用。TLB 在擴充性方面存在缺陷，VB 不使用 TLB。
* 約定的工作方式是基於類型描述的，所採用的型別系統是 C++ 的可移植子集。而且 COM 對元件的約定是物理的二進位約定，要求每個方法都具有精確的虛擬函式表偏移量、每個被傳遞的參數在堆疊規則中都有明確的偏移量、物件參照採用介面指標的明確格式、使用規定的分配器進行被呼叫這記憶體分配。COM 元件的約定的精確性，產生了高效的程式碼；但不可靠性、開發使用及擴充升級的困難與複雜性高昂。

## 參見

* 可移植物件，跨語言跨平台物件模型定義
* Distributed COM（DCOM），使 COM 能在網路中工作的擴充
* 通用語言架構，當前的.NET 跨語言跨平台物件模型
* Windows Runtime，應用程式模型，指向 Windows 8 的 COM 演進版本
* CORBA，通用物件請求代理體系結構，開放式跨平台物件模型
* D-Bus，開放跨語言跨平台物件模型
* KDE Frameworks 5 KDE 元件框架
* SOM，IBM 系統物件模型，功能豐富的 COM 替代品
* XPCOM，Mozilla 應用程式跨平台元件物件模型
* JavaBeans
* Java 遠端方法呼叫
* ICE (中介軟體)
* 綁紮
* Foreign function interface
* 呼叫約定
* 名字修飾
* 應用程式介面 - API
* 套用二進位介面 - ABI
* SWIG，開源自動介面繫結生成器，從許多語言到其他語言

## 參考文獻

* COM: A Brief Introduction (powerpoint). [March 7, 2006]. （原始內容存檔於 2007-11-29）.
* Box, Don. Essential COM. Addison-Wesley. 1998. ISBN 0-201-63446-5.
* Chappell, David. Understanding ActiveX and OLE. Microsoft Press. 1996. ISBN 978-1-57231-216-6.
* Integration and Migration of COM+ services to WCF. [April 15, 2010]. （原始內容存檔於 2018-09-07）.

## 外部連結

* Microsoft COM Technologies （頁面存檔備份，存於網際網路檔案館）
* Interview with Tony Williams, Co-Inventor of COM （頁面存檔備份，存於網際網路檔案館）（Video Webcast, August 2006）
* A concise technical overview of COM （頁面存檔備份，存於網際網路檔案館） from master's thesis
* Info: Difference Between OLE Controls and ActiveX Controls （頁面存檔備份，存於網際網路檔案館） from Microsoft
* TypeLib Data Format Specification (unofficial) （頁面存檔備份，存於網際網路檔案館） with open source dumper utility.
* The COM / DCOM Glossary