コンポーネントオブジェクトモデル

ウィキペディアから、無料の百科事典
ナビゲーションにジャンプ 検索にジャンプ

COM
コンポーネントオブジェクトモデル
略語COM
スターテス有効
初版1993 ; 29年前 (1993
最新バージョン生活水準
2021
組織マイクロソフト
シリーズシステムサービス
基本基準MIDLUUID
関連規格
ドメインコンポーネントインターフェース
Webサイトdocs .microsoft .com / en-us / windows / win32 / com / the-component-object-model

コンポーネントオブジェクトモデルCOM)は、1993年にMicrosoftによって導入されたソフトウェアコンポーネントのバイナリインターフェイス標準です。これは、さまざまなプログラミング言語でプロセス間通信オブジェクトを作成できるようにするために使用されますCOMは、OLEOLEオートメーションブラウザヘルパーオブジェクトActiveXCOM +DCOMWindowsシェルDirectXUMDF WindowsランタイムCOMの本質は、マシンの境界を越えても、オブジェクトが作成された環境とは異なる環境で使用できるオブジェクトを実装する言語に依存しない方法です。適切に作成されたコンポーネントの場合、COMを使用すると、コンポーネントの実装者は実装から分離された明確に定義されたインターフェイスを提供する必要があるため、内部実装の知識がなくてもオブジェクトを再利用できます。言語のさまざまな割り当てセマンティクスは、参照カウントを通じてオブジェクトが自身の作成と破棄を担当するようにすることで対応されますオブジェクトの異なるインターフェース間の型変換キャストは、QueryInterface方法。COM内の「継承」の推奨される方法は、メソッドの「呼び出し」が委任されるサブオブジェクトの作成です。

COMは、 MicrosoftWindowsおよびAppleのCoreFoundation 1.3以降のプラグインアプリケーションプログラミングインターフェイス(API)でのみ標準として定義および実装されているインターフェイステクノロジです。[1]後者は、COMインターフェース全体のサブセットのみを実装します。[2]一部のアプリケーションでは、COMは少なくともある程度Microsoft .NET Frameworkに置き換えられており、 Windows Communication Foundation(WCF)を介したWebサービスのサポートがあります。ただし、COMオブジェクトは、.NET COMInteropを介してすべての.NET言語で使用できますネットワーク化されたDCOMは、バイナリ独自の形式を使用します、WCFはXMLベースのSOAPメッセージングの使用を推奨しています。COMは、 CORBAEnterprise JavaBeansなどの他のコンポーネントソフトウェアインターフェイステクノロジと非常に似ていますが、それぞれに長所と短所があります。C ++とは異なり、COMは、コンパイラのリリース間で変更されない安定したアプリケーションバイナリインターフェイス(ABI)を提供します。[3]これにより、COMインターフェースは、異なるコンパイラバージョンを使用してコンパイルされたクライアントによって使用されるオブジェクト指向C ++ライブラリにとって魅力的なものになります。

歴史

Windowsでのプロセス間通信の最初の方法の1つは、動的データ交換(DDE)であり[4] 1987年に最初に導入され[5]、アプリケーション間のいわゆる「会話」でメッセージを送受信できるようになりました。COMアーキテクチャの作成に携わったAntonyWilliamsは、ソフトウェアコンポーネントの概念を取り入れた2つの内部論文をMicrosoftで配布しました。オブジェクトアーキテクチャ:未知の問題への対処–または–動的に拡張可能なクラスライブラリの型安全性1988年と継承について: 1990年の意味と使用方法。これらは、COMの背後にある多くのアイデアの基礎を提供しました。Microsoftの最初のオブジェクトベースのフレームワークであるObjectLinking and Embedding (OLE)は、DDEの上に構築され、複合ドキュメント用に特別に設計されました1991年にWordfor WindowsExcelで導入され、1992年のバージョン3.1からWindowsに組み込まれました。複合ドキュメントの例は、Word forWindowsドキュメントに埋め込まれたスプレッドシートです。スプレッドシートに変更が加えられるためです。 Excel内では、Wordドキュメント内に自動的に表示されます。

1991年、MicrosoftはVisual Basic1.0でVisualBasic Extensions(VBX)を導入しました。VBXは、ダイナミックリンクライブラリ(DLL)の形式でパッケージ化された拡張機能であり、オブジェクトをフォームにグラフィカルに配置し、プロパティメソッドで操作できるようにします。これらは、後でVisual C ++などの他の言語で使用できるように調整されました1992年にWindowsのバージョン3.1がリリースされたとき、Microsoftはその基礎となるオブジェクトモデルとともにOLE2をリリースしました。COMアプリケーションのバイナリインターフェイス(ABI)は、MAPI ABI(1992年にリリース)と同じであり、MSRPCに基づいており、最終的にはGroupDCE / RPCを開きます。OLE 1は複合ドキュメントに重点を置いていましたが、COMとOLE2は一般的なソフトウェアコンポーネントに対応するように設計されていました。テキスト会話とWindowsメッセージは、堅牢で拡張可能な方法でアプリケーション機能を共有できるほど柔軟ではないことが判明したため、COMが新しい基盤として作成され、OLEがOLE2に変更されました。1994年に、 OLEカスタムコントロール(OCX)がVBXコントロールの後継として導入されました。同時に、Microsoftは、OLE 2は単に「OLE」と呼ばれ、OLEはもはや頭字語ではなく、会社のすべてのコンポーネントテクノロジの名前であると述べました。1996年の初めに、MicrosoftはOLEカスタムコントロールの新しい使用法を発見し、コンテンツを表示するWebブラウザの機能を拡張しました。インターネットActiveX 」、およびMicrosoftOfficeで使用されていた複合ドキュメントテクノロジを除くすべてのOLEテクノロジの名前を徐々にActiveXに変更しましたその年の後半、MicrosoftはCOMを拡張して、DCOMを使用してネットワーク全体で機能するようにしました。[6]

関連技術

COMは、Windowsの主要なソフトウェア開発プラットフォームであり、そのため、多くのサポートテクノロジの開発に影響を与えました。同様に、以前のテクノロジーの影響を強く受けていました。

DDE

COMは、プロセス間通信の優先形式として DDEに取って代わりました。

DCE / RPCおよびMSRPC

クロスランゲージコンポーネントモデルとして、COMはインターフェイス定義言語(IDL)に依存して、オブジェクトと関連する機能を記述します。COM IDLは、機能豊富なDCE / RPC IDLに大きく基づいており、オブジェクト指向の拡張機能を備えています。MSRPCとして知られるMicrosoft独自のDCE / RPCの実装は、Windows NTサービスおよび内部コンポーネントの主要なプロセス間通信メカニズムとして頻繁に使用されており、基盤として明確に選択されています。

DCOM

DCOM(Distributed COM)は、Windowsデスクトップ上で通信する個別のアプリケーションで単一のユーザーをサポートするだけでなく、さまざまなセキュリティコンテキストで、ネットワーク上のさまざまなマシンで実行されているオブジェクトをアクティブ化するまで、COMの範囲を拡大しました。これに伴い、オブジェクトの作成、アクティブ化、呼び出しの権限を持つユーザーの構成、呼び出し元のユーザーの識別、および呼び出しのセキュリティに必要な暗号化の指定に必要な機能が追加されました。

COM +

マイクロソフトが開発者に分散トランザクション、リソースプーリング、切断されたアプリケーション、イベントの公開とサブスクリプション、より優れたメモリとプロセッサ(スレッド)管理のサポートを提供し、Windowsを他のエンタープライズレベルのオペレーティングシステムの代替として位置付けるために、 Microsoftは、 Windows NT4にMicrosoftTransaction Server (MTS)と呼ばれるテクノロジを導入しました。Windows2000では、COMの重要な拡張機能がオペレーティングシステムに組み込まれ( MTSが提供する一連の外部ツールとは対照的に)、 COM +に名前が変更されました同時に、MicrosoftはDCOMを重視していませんでした別のエンティティとして。COM +サービスを利用したコンポーネントは、COM +の追加レイヤーによって、特にインターセプトのオペレーティングシステムサポートによって、より直接的に処理されました。MTSの最初のリリースでは、傍受が取り組まれていました。MTSコンポーネントをインストールすると、コンポーネントを直接呼び出すのではなく、MTSソフトウェアを呼び出すようにWindowsレジストリが変更されます。Windows 2000は、COM +コンポーネントの構成に使用されるコンポーネントサービスのコントロールパネルアプリケーションも改訂しました。

COM +の利点は、「コンポーネントファーム」で実行できることでした。コンポーネントのインスタンスは、適切にコーディングされていれば、メモリからアンロードせずに、初期化ルーチンへの新しい呼び出しによってプールされ、再利用される可能性があります。コンポーネントを配布することもできます(別のマシンから呼び出されます)。COM +とMicrosoftVisual Studioは、クライアント側のプロキシを簡単に生成できるツールを提供していたため、リモート呼び出しにはDCOMを使用しましたが、開発者にとっては簡単に実行できました。COM +は、 COM +イベントと呼ばれるサブスクライバー/パブリッシャーイベントメカニズムも導入し、キューに入れられたコンポーネントと呼ばれるコンポーネントでMSMQ(アプリケーション間非同期メッセージングを提供するテクノロジー)を活用する新しい方法を提供しました。COM +イベントは、COM +プログラミングモデルを拡張して、パブリッシャーまたはサブスクライバーとイベントシステム間の遅延バインド(遅延バインディングを参照)イベントまたはメソッド呼び出しをサポートします。

.NET

Microsoft .NETは、コンポーネントテクノロジを提供する手段と、COM +と対話する手段(COM-interop-assembliesを介して)の両方を提供します。.NETは、一般的に使用されるほとんどのCOMコントロールへのラッパーを提供します。Microsoft .NETは、コンポーネントの作成からほとんどの詳細を隠しているため、開発が容易です。.NETはSystem.EnterpriseServices名前空間を介してCOM +を活用でき、COM +が提供するサービスのいくつかは.NETの最近のリリースで複製されています。たとえば、.NETのSystem.Transactions名前空間は、COM +に頼らずにトランザクション管理を提供するTransactionScopeクラスを提供します。同様に、キューに入れられたコンポーネントは、MSMQを使用するWindows CommunicationFoundationで置き換えることができます。輸送。(ただし、MSMQはネイティブCOMコンポーネントです。)下位互換性のサポートには制限があります。COMオブジェクトは、Runtime Callable Wrapper(RCW)を実装することにより、.NETで使用できます。[7]特定のインターフェイス制限に準拠するNETオブジェクトは、 COM呼び出し可能ラッパー(CCW)を呼び出すことによってCOMオブジェクトで使用できます。[8] COM側と.NET側の両方から、他のテクノロジを使用するオブジェクトはネイティブオブジェクトとして表示されます。COM相互運用機能を参照してくださいWCF(Windows Communication Foundation)は、COMのリモート実行に関する多くの課題を緩和します。たとえば、プロセスまたはマシンの境界を越えて、オブジェクトを値によって透過的にマーシャリングすることがより簡単になります。

Windowsランタイム

Microsoftの新しいWindowsランタイム(またはWindows RTと混同しないようにWinRT )のプログラミングおよびアプリケーションモデルは、拡張COMに依存していますが、基本的にCOMベースのAPIです。COMに似た基盤があるため、Windowsランタイムでは、COMと同様に、複数の言語からの比較的簡単なインターフェイスが可能ですが、基本的には管理されていないネイティブAPIです。ただし、API定義は「.winmd」ファイルに保存されます。このファイルは、.NETがいくつかの変更を加えて使用するのと同じCLIメタデータ形式であるECMA335メタデータ形式でエンコードされます。この一般的なメタデータ形式では、WinRTが.NETアプリケーションから呼び出されたときに、P / Invokeよりも大幅にオーバーヘッドが少なくなり、構文がはるかに単純になります。

Nano-COM(別名XPCOM)

Nano-COMは、コンポーネントオブジェクトモデルの非常に小さなサブセットであり、COMのアプリケーションバイナリインターフェイス(ABI)の側面にのみ焦点を当てており、独立してコンパイルされたモジュール/コンポーネント間で関数とメソッドの呼び出しを可能にします。Nano-COMは、すべてのC ++コンパイラに移植可能な単一のC ++ヘッダーファイルで簡単に表現できます。Nano-COMは、基盤となる命令アーキテクチャとOSのネイティブABIを拡張して、型付きオブジェクト参照のサポートを追加します(通常のABIは、アトミックタイプ、構造、配列、および関数呼び出し規約にのみ焦点を当てています)。Nano-COMの基盤は、Firefox(XPCOMと呼ばれる)をブートストラップするためにMozillaによって使用され、現在、 DirectX / Direct3D / DirectMLのベースABIテクノロジーとして使用されています。

Nano-COMヘッダーファイルは、少なくとも3つのタイプを定義または命名します。

  • インターフェイスタイプを識別するためのGUID-これは事実上128ビットの数値です
  • メソッド呼び出しからエラーコードを識別するためのHRESULT-これは事実上、既知の値(S_OK、E_FAIL、E_OUTOFMEMORYなど)に対する32ビットintの標準化された使用法です。
  • IUnknownは、すべての型指定されたオブジェクト参照の基本型として知られていません-これはdynamic_cast<T>、新しいインターフェイス型のスタイル取得と参照カウントをサポートするための事実上抽象的な仮想関数ですshared_ptr<T>

Nano-COMの多くの使用法では、結果として呼び出し先に割り当てられたメモリバッファをアドレス指定する2つの関数も定義されています。

  • <NanoCom> Alloc –呼び出し元に返されるrawバッファー(オブジェクトではない)を割り当てるためにメソッド実装によって呼び出されます
  • <NanoCom> Free –メソッドの呼び出し元によって呼び出され、使用されなくなった呼び出し先に割り当てられたバッファーを解放します

Direct3DなどのNano-COMの一部の実装では、アロケーター関数を避け、呼び出し元が割り当てたバッファーのみを使用するように制限しています。

Nano-COMには、クラス、アパートメント、マーシャリング、登録などの概念はありません。むしろ、オブジェクト参照は関数の境界を越えて渡され、標準の言語構造(C ++のnew演算子など)を介して割り当てられます。

セキュリティ

COMおよびActiveXコンポーネントは、サンドボックスを使用せずに、ユーザーのマシン上でネイティブコードとして実行されます。したがって、コードで実行できることにはほとんど制限がありません。したがって、 Internet Explorerを使用してWebページにActiveXコンポーネントを埋め込む以前の方法では、マルウェア感染の問題が発生していました。マイクロソフトは、チャールズ・フィッツジェラルドが「ActiveXが本質的に安全であると前もって主張したことは一度もない」と言った1996年まで、ActiveXの問題を認識していました。[9]最近の[いつ?] Internet Explorerのバージョンは、ActiveXコントロールをインストールする前にユーザーにプロンプ​​トを表示し、ユーザーが信頼していないサイトからのコントロールのインストールを禁止できるようにします。ActiveXコントロールは署名されていますそれらの信頼性を保証するためデジタル署名を使用します。ActiveXコントロールを完全に無効にしたり、選択した少数のコントロールのみを許可したりすることもできます。アウトプロセスCOMサーバーの透過的なサポートにより、プロセスの分離という観点からソフトウェアの安全性が向上します。これは、大規模なアプリケーションのサブシステムを個別のプロセスに分離する場合に役立ちます。プロセスの分離は、厳密に定義されたインターフェイスを介してのみ通信するため、1つのプロセスの状態の破損が他のプロセスの整合性に悪影響を与えることを制限します。したがって、有効な状態を回復するには、影響を受けるサブシステムのみを再起動する必要があります。これは、不正なポインタが存在する同じプロセス内のサブシステムには当てはまりません。1つのサブシステムで、他のサブシステムがランダムに破損する可能性があります。

技術的な詳細

COMプログラマーは、COM対応コンポーネントを使用してソフトウェアを構築します。さまざまなコンポーネントタイプは、グローバル一意識別子(GUID)であるクラスID(CLSID)によって識別されます。各COMコンポーネントは、1つ以上のインターフェイスを介してその機能を公開します。コンポーネントでサポートされているさまざまなインターフェイスは、GUIDでもあるインターフェイスID(IID)を使用して互いに区別されます。COMインターフェイスには、 CC ++Visual BasicDelphiPythonなどのいくつかの言語でのバインディングがあります[10] [11]Windowsプラットフォームに実装されているスクリプト言語のいくつか。コンポーネントへのすべてのアクセスは、インターフェースのメソッドを介して行われます。これにより、プロセス間、またはコンピューター間プログラミング(後者はDCOMのサポートを使用)などの手法が可能になります。

インターフェイス

すべてのCOMコンポーネントは、参照カウント型変換(キャスト)のメソッドを公開するIUnknownカスタム)インターフェイスを実装しています。カスタムIUnknownインターフェイスは、インターフェイスで宣言されたのと同じ順序で、インターフェイスで宣言された関数を実装する関数へのポインタのリストを含む仮想メソッドテーブルへのポインタで構成されます。したがって、インプロセス呼び出しのオーバーヘッドは、C ++の仮想メソッド呼び出しに匹敵します。カスタムインターフェイスに加えて、COMはIDispatchから継承するディスパッチインターフェイスもサポートしますディスパッチインターフェイスは、 OLEオートメーションの遅延バインディングをサポートしていますこれにより、ディスパッチインターフェイスにカスタムインターフェイスよりも幅広いプログラミング言語からネイティブにアクセスできます。

クラス

COMクラス(「コクラス」)は、1つ以上のインターフェースの具体的な実装であり、オブジェクト指向プログラミング言語のクラスによく似ています。クラスは、クラスID(CLSID)またはプログラムID文字列(ProgID)に基づいて作成されます。多くのオブジェクト指向言語と同様に、COMはインターフェースを実装から分離します。この区別は、オブジェクトに直接アクセスできず、インターフェイスを介してのみアクセスできるCOMで特に強くなります。COMは、同じインターフェイスの複数の実装もサポートしているため、実行時にクライアントは、インスタンス化するインターフェイスの実装を選択できます。

インターフェイス定義言語およびタイプライブラリ

タイプライブラリには、COMタイプを表すメタデータが含まれています。これらのタイプは、Microsoftインターフェイス定義言語(MSIDL / IDL)を使用して記述されます。IDLファイルは、オブジェクト指向のクラス、インターフェイス、構造、列挙型、およびその他のユーザー定義型を言語に依存しない方法で定義します。IDLは、C ++宣言と外観が似ていますが、インターフェイスとクラスのコレクションを定義するための「interface」や「library」などのいくつかの追加キーワードがあります。IDLは、宣言の前に括弧で囲まれた属性を使用して、インターフェイスGUIDやポインターパラメーターと長さフィールドの関係などの追加情報を提供することもサポートしています。IDLファイルはMIDLコンパイラによってコンパイルされますC / C ++の場合、MIDLコンパイラは、宣言されたインターフェイスのvtblに一致する構造体定義を含むコンパイラに依存しないヘッダーファイルと、インターフェイスGUIDの宣言を含むCファイルを生成します。プロキシモジュールのC ++ソースコードは、MIDLコンパイラによって生成することもできます。このプロキシには、COM呼び出しをリモートプロシージャ呼び出しに変換するためのメソッドスタブが含まれていますDCOMがアウトプロセス通信を有効にするため。IDLファイルは、MIDLコンパイラによってタイプライブラリ(TLB)にコンパイルすることもできます。TLBファイルには、TLBで定義されたCOMタイプを表す言語固有の構造を生成するために、さまざまな言語コンパイラおよびランタイム環境(VB、Delphi、.NETなど)で処理できるバイナリメタデータが含まれています。C ++の場合、これによりTLBがIDL表現に変換されます。

オブジェクトフレームワーク

COMはランタイムフレームワークであるため、タイプは実行時に個別に識別および指定可能である必要があります。これを実現するために、グローバル一意識別子(GUID)が使用されます。各COMタイプは、実行時に識別するための独自のGUIDに指定されています。コンパイル時と実行時の両方でCOMタイプに関する情報にアクセスできるようにするために、COMはタイプライブラリを使用します。COMがオブジェクトの相互作用のための動的フレームワークとしての機能を実現する のは、タイプライブラリを効果的に使用することによってです。

IDLでの次のコクラス定義の例を検討してください。

コクラスSomeClass {
  [デフォルト]インターフェイスISomeInterface;
};

上記のコードフラグメントは、というSomeClass名前のインターフェイスを実装するという名前のCOMクラスを宣言しますISomeInterface

これは、概念的には次のC ++クラスを定義することと同じです。

クラス SomeClass public ISomeInterface {    
  ..。
  ..。
};

ここで、ISomeInterfaceはC ++の純粋仮想クラス(抽象基本クラスと呼ばれることもあります)です。

COMインターフェイスとクラスを含むIDLファイルは、タイプライブラリ(TLB)ファイルにコンパイルされます。このファイルは、後でクライアントが実行時に解析して、オブジェクトがサポートするインターフェイスを判別し、オブジェクトのインターフェイスメソッドを呼び出すことができます。

C ++では、COMオブジェクトはCoCreateInstance、クラスID(CLSID)とインターフェイスID(IID)を引数として取る関数を使用してインスタンス化されます。のインスタンス化はSomeClass、次のように実装できます。

ISomeInterface * interface_ptr = NULL ;   
HRESULT hr = CoCreateInstance CLSID_SomeClass NULL CLSCTX_ALL      
                              IID_ISomeInterface void ** interface_ptr ); 

この例では、COMサブシステムを使用して、インターフェースを実装するオブジェクトへのポインターを取得しますISomeInterface。このインターフェースのコクラスCLSID_SomeClassの特定の実装が必要です。

参照カウント

すべてのCOMオブジェクトは、参照カウントを利用してオブジェクトの有効期間を管理します。参照カウントは、すべてのCOMオブジェクトが実装する必須のIUnknownインターフェイスのAddRefメソッドとReleaseメソッドを介してクライアントによって制御されます。COMオブジェクトは、参照カウントがゼロに低下したときに、自身のメモリを解放する責任があります。特定の言語(Visual Basicなど)は自動参照カウントを提供するため、COMオブジェクト開発者はソースコードで内部参照カウンターを明示的に維持する必要がありません。C ++では、コーダーは明示的な参照カウントを実行するか、スマートポインターを使用して参照カウントを自動的に管理します。

以下は、COMオブジェクトで AddRefReleaseを呼び出すタイミングのガイドラインです。

  • (戻り値または「out」パラメーターを介して)インターフェース参照を返す関数およびメソッドは、返される前に、返されたオブジェクトの参照カウントをインクリメントする必要があります。
  • ポインタが上書きされるかスコープ外になる前に、インターフェイスポインタでリリースを呼び出す必要があります。
  • インターフェイス参照ポインタでコピーが作成される場合は、そのポインタでAddRefを呼び出す必要があります。
  • AddRefReleaseは、参照されている特定のインターフェイスで呼び出す必要があります。これは、オブジェクトが、参照されているインターフェイスにのみ内部リソースを割り当てるために、インターフェイスごとの参照カウントを実装する場合があるためです。

すべての参照カウント呼び出しがネットワーク経由でリモートオブジェクトに送信されるわけではありません。プロキシは、リモートオブジェクトに1つの参照のみを保持し、独自のローカル参照カウントを維持します。COM開発を簡素化するために、MicrosoftはC ++開発者向けにATL(Active Template Library)を導入しました。ATLは、より高いレベルのCOM開発パラダイムを提供します。また、スマートポインターオブジェクトを提供することにより、COMクライアントアプリケーション開発者を参照カウントを直接維持する必要から保護します。COM対応の他のライブラリと言語には、Microsoft Foundation ClassesVCコンパイラCOMサポート、[12] VBScriptVisual BasicECMAScriptJavaScript )が含まれます。)およびBorlandDelphi

プログラミング

COMは、言語に依存しないバイナリ標準であり、バイナリで定義されたデータ型とインターフェイスを理解して実装できる任意のプログラミング言語で開発できます。COM実装は、COM環境への出入り、COMオブジェクトのインスタンス化と参照カウント、サポートされているインターフェイスのオブジェクトのクエリ、およびエラーの処理を担当します。Microsoft Visual C ++コンパイラは、C ++属性と呼ばれるC ++言語の拡張機能をサポートしています。[13]これらの拡張機能は、COM開発を簡素化し、C ++でCOMサーバーを実装するために必要な定型コードの多くを削除するように設計されています。[14]

レジストリの使用法

Windowsでは、COMクラス、インターフェイス、およびタイプライブラリは、レジストリのGUIDによって、クラスの場合はHKEY_CLASSES_ROOT \ CLSIDの下に、インターフェイスの場合はHKEY_CLASSES_ROOT \ Interfaceの下に一覧表示されます。COMライブラリは、レジストリを使用して、各COMオブジェクトの正しいローカルライブラリまたはリモートサービスのネットワークロケーションを検索します。

登録不要のCOM

登録不要のCOM(RegFree COM)は、Windows XPで導入されたテクノロジであり、コンポーネントオブジェクトモデル(COM)コンポーネントが、レジストリを使用せずにコンポーネントのアクティベーションメタデータとCLSID( )を格納できるようにします代わりに、コンポーネントに実装されたクラスのメタデータとCLSIDは、アセンブリマニフェストXMLを使用して記述)で宣言され、実行可能ファイルのリソースとして、またはコンポーネントとともにインストールされた別のファイルとして保存されます。[15]これにより、同じコンポーネントの複数のバージョンを、独自のマニフェストによって記述された異なるディレクトリにインストールしたり、XCOPYを展開したりできます。Class ID[16]この手法はEXECOMサーバーのサポートが制限されており[17] 、 MDAC MSXML DirectX InternetExplorerなどのシステム全体のコンポーネントには使用できません

アプリケーションのロード中に、Windowsローダーはマニフェストを検索します。[18]存在する場合、ローダーはそこからアクティベーションコンテキストに情報を追加します。[16] COMクラスファクトリがクラスをインスタンス化しようとすると、最初にアクティベーションコンテキストがチェックされ、CLSIDの実装が見つかるかどうかが確認されます。ルックアップが失敗した場合にのみ、レジストリがスキャンされます。[16]

COMオブジェクトを手動でインスタンス化する

DLLファイルのパスとオブジェクトのGUIDを指定して、COMオブジェクトを手動で作成することもできます。これには、DLLまたはGUIDをシステムレジストリに登録する必要はなく、マニフェストファイルを使用しません。COM DLLは、DllGetClassObjectという名前の関数をエクスポートします。目的のGUIDとIID_IClassFactoryを使用してDllGetClassObjectを呼び出すと、ファクトリオブジェクトのインスタンスが提供されます。FactoryオブジェクトにはCreateInstanceメソッドがあり、インターフェイスGUIDを指定してオブジェクトのインスタンスを作成できます。[19]これは、登録されたCOMコンポーネントのインスタンスを作成するときに内部的に使用されるプロセスと同じです。[20]

作成されたCOMオブジェクトが汎用CoCreateInstanceAPIを使用して別のCOMオブジェクトをインスタンス化する場合、レジストリまたはマニフェストファイルを使用して、通常の汎用的な方法でインスタンス化を試みます。ただし、内部オブジェクト(まったく登録されていない可能性があります)を作成し、独自の個人的な知識を使用して、それらへのインターフェイスへの参照を渡すことができます。

プロセスとネットワークの透過性

COMオブジェクトは、同じプロセス内(インプロセス)、プロセス境界を越えて(アウトプロセス)、またはネットワーク経由でリモート(DCOM)から透過的にインスタンス化および参照できます。アウトプロセスオブジェクトとリモートオブジェクトは、マーシャリングを使用してメソッド呼び出しをシリアル化し、プロセスまたはネットワークの境界を越えて値を返します。このマーシャリングは、ローカルのインプロセスオブジェクトであるかのようにオブジェクトにアクセスするクライアントには表示されません。

糸脱毛

COMでは、スレッドはアパートと呼ばれる概念を通じて対処されます[21]個々のCOMオブジェクトは、シングルスレッドまたはマルチスレッドのいずれかである1つのアパートメントにのみ存在します。COMには、シングルスレッドアパートメント(STA)マルチスレッドアパートメント(MTA)スレッドニュートラルアパートメントの3種類のアパートメントがあります。(NA)。各アパートメントは、オブジェクトの内部状態を複数のスレッド間で同期できる1つのメカニズムを表しています。プロセスは複数のCOMオブジェクトで構成でき、その一部はSTAを使用し、その他はMTAを使用する場合があります。COMオブジェクトにアクセスするすべてのスレッドは、同様に1つのアパートメントに存在します。COMオブジェクトとスレッドのアパートメントの選択は実行時に決定され、変更することはできません。

アパートタイプ 説明
シングルスレッドアパートメント[22]STA)、(ThreadingModel = Apartment 単一のスレッドは、オブジェクトのメソッドを実行するために使用されます。このような配置では、アパートメントの外部のスレッドからのメソッド呼び出しがマーシャリングされ、システムによって自動的にキューに入れられます(標準のWindowsメッセージキューを介して)。したがって、COMランタイムは自動同期を提供して、オブジェクトの各メソッド呼び出しが常に実行されてから、別のオブジェクトが呼び出されるようにします。したがって、開発者はスレッドのロックや競合状態について心配する必要はありません。
マルチスレッドアパートメント[23]MTA)、(ThreadingModel = Free COMランタイムは同期を提供せず、複数のスレッドがCOMオブジェクトを同時に呼び出すことができます。したがって、COMオブジェクトは、複数のスレッドからの同時アクセスが競合状態を引き起こすのを防ぐために、独自の同期を実行する必要があります。STA内のスレッドからのMTAオブジェクトへの呼び出しもマーシャリングされます。
動的に決定されたアパート(ThreadingModel =両方 両方アパートメントモードでは、サーバーはオブジェクトの作成時にSTAまたはMTAを自動選択して、呼び出し元のスレッドのアパートメントタイプと一致させます。[24]これは、MTAサーバーがSTAスレッドによってアクセスされるときにオーバーヘッドをマーシャリングすることを回避するのに役立ちます。
スレッドニュートラルアパートメントNA)、(ThreadingModel =ニュートラル スレッドが割り当てられていない特別なアパート。STAまたはMTAスレッドが同じプロセスでNAオブジェクトを呼び出すと、呼び出し元のスレッドは一時的にそのアパートメントを離れ、スレッドを切り替えることなくNAで直接コードを実行します。[25]したがって、NAは効率的なアパート間メソッド呼び出しの最適化と考えることができます。

同じアパートメントに属するスレッドとオブジェクトは、同じスレッドアクセスルールに従います。したがって、同じアパート内で行われるメソッド呼び出しは、COMの支援なしで直接実行されます。アパート間で行われるメソッド呼び出しは、マーシャリングを介して実行されます。これには、プロキシとスタブを使用する必要があります。

批判

COMの実装はかなり複雑であるため、プログラマーは「配管」の問題のいくつかに気を取られる可能性があります。

メッセージポンピング

STAが初期化されると、アパートメント間およびプロセス間メッセージルーティングに使用される非表示のウィンドウが作成されます。このウィンドウでは、メッセージキューを定期的に「ポンプ」する必要があります。この構成は「メッセージポンプ」として知られています。以前のバージョンのWindowsでは、そうしないと、システム全体のデッドロックが発生する可能性がありました。この問題は、実装の一部としてCOMを初期化する一部のWindows APIによって複雑になり、実装の詳細の「リーク」が発生します。

参照カウント

2つ以上のオブジェクトが循環参照されている場合、COM内の参照カウントで問題が発生する可能性がありますアプリケーションの設計では、オブジェクトが孤立したままにならないように、これを考慮に入れる必要があります。COM「イベントシンク」モデルが使用されている場合、オブジェクトにはアクティブな参照カウントが残る場合もあります。イベントを発生させるオブジェクトは、イベントに反応するオブジェクトへの参照を必要とするため、後者の参照カウントがゼロに達することはありません。参照サイクルは通常、帯域外終端または分割IDのいずれかを使用して中断されます。帯域外終了手法では、オブジェクトはメソッドを公開します。このメソッドは、呼び出されると、他のオブジェクトへの参照を強制的に削除し、それによってサイクルを中断します。分割ID手法では、1つの実装で2つの別個のCOMオブジェクト(IDとも呼ばれます)が公開されます。これにより、COMオブジェクト間に弱い参照が作成され、参照サイクルが妨げられます。

DLL地獄

インプロセスCOMコンポーネントはDLLファイルに実装されており、登録ではCLSIDごとに1つのバージョンしか許可されないため、状況によっては「DLL地獄」の影響を受ける可能性があります。登録不要のCOM機能により、インプロセスコンポーネントのこの問題が解消されます。登録不要のCOMは、アウトプロセスサーバーでは使用できません。

も参照してください

メモ

  1. ^ 「ドキュメントアーカイブ」developer.apple.com
  2. ^ 「プラグインとMicrosoftのCOM」Apple Inc. 2010年10月5日取得
  3. ^ Microsoftフォーラム: Visual C ++バージョン間のバイナリ互換性
  4. ^ 「ネットワークDDEについて-Windowsアプリケーション」Microsoft.com_ 2018年5月30日。
  5. ^ 「コード実行技術は動的データ交換を利用します」McAfee.com_ 2017年10月27日。
  6. ^ ブラウン、ニーナ; キンデル、チャーリー(1998年3月11日)。"draft-brown-dcom-v1-spec-03-分散コンポーネントオブジェクトモデルプロトコル-DCOM / 1.0"datatracker.ietf.org 2019年8月29日取得
  7. ^ rpetrusha。「ランタイム呼び出し可能ラッパー」msdn.microsoft.com
  8. ^ rpetrusha。「COM呼び出し可能ラッパー」msdn.microsoft.com
  9. ^ スタインバーグ、ジル(1997年3月1日)。「競合するコンポーネントは、とげのあるパネリストになります」JavaWorld2020年7月16日取得
  10. ^ 「win32comドキュメントインデックス」docs.activestate.com
  11. ^ 「PythonとCOM」www.boddie.org.uk
  12. ^ 「コンパイラCOMサポート」MSDNマイクロソフト。
  13. ^ Microsoft MSDN: C ++属性リファレンス
  14. ^ MSDN Magazine: C ++属性:Visual Studio.NETの新機能でCOMプログラミングを簡単にします
  15. ^ 「アセンブリマニフェスト」MSDN 2009年11月5日取得
  16. ^ a bc デイブテンプリン「ClickOnceと登録不要のCOMを使用してアプリの展開を簡素化する」MSDNマガジン2008年4月22日取得
  17. ^ 「tlbファイルなしでアウトプロセスCOMサーバーを使用する方法」2011年4月16日取得
  18. ^ 「分離アプリケーションとサイドバイサイドアセンブリの概念」MSDN 2016年2月5日取得
  19. ^ アルキポフ、ミハイル(2005年4月1日)。「登録不要のCOM」MSDNブログ2016年4月29日取得
  20. ^ 「DllGetClassObjectエントリポイント(COM)」MSDNCoGetClassObject関数の呼び出しで、DLLにロードされるクラスオブジェクトが見つかった場合、CoGetClassObjectはDLLのエクスポートされたDllGetClassObject関数を使用します。
  21. ^ Microsoft MSDN:プロセス、スレッド、およびアパート
  22. ^ Microsoft MSDN:シングルスレッドアパート
  23. ^ Microsoft MSDN:マルチスレッドアパート
  24. ^ Microsoft MSDN: COMスレッドモデルの理解と使用
  25. ^ Codeguru: COMアパートを理解する

参考文献

外部リンク