-
Notifications
You must be signed in to change notification settings - Fork 0
MS_COM
- 戻る(コンポーネント技術)
- COM
- STA / MTA
- DLL/COMユーザ
-
COM (Component Object Model) は、
- Microsoft が作り出した、プログラムや部品の呼び出しを共通的に行える仕組み。
- COM をベースに、COM コンポーネント、ActiveX コントロールなどの部品が
作られてきた。
-
COM に関しては、下のページも参考ください。
補足(COM の要点): COM の本質は
「バイナリ レベルでのインターフェイス規約」である。
- 言語もコンパイラも問わない(C++ / VB / C# / VBS から同じ部品を使える)。
- すべてのインターフェイスは
IUnknownを継承し、
QueryInterface/AddRef/Releaseの 3 メソッドを必ず持つ。- オブジェクトの寿命は参照カウントで管理される(GC ではない)。
この「参照カウント」が、後述のCOM のメモリ・リークの
直接の原因になる。
COM を利用する際は、ProgID を使用して、
COM 部品のオブジェクトを得ます。
-
VBSの例(作成する場合)
set fso = CreateObject("Scripting.FileSystemObject")
-
VBSの例(作成済みのオブジェクトを取得する場合)
set word = GetObject("c:\temp\word.doc", "Word.Document")
Scripting.FileSystemObject や Word.Document は ProgID の例です。
ProgID は、レジストリの HKEY_CLASSES_ROOT に書かれています。
- インターフェイス変更が認められている。
- インターフェイスが変更されると CLSID, IID などのIDも変更される。
- インターフェイス変更はメソッド追加だけが認められている。
- 仮想関数メカニズムを利用し、継承したインターフェイスにメソッドを追加する。
- このため、既存の CLSID, IID は変更されず、
新しいインターフェイスの IID ダケが追加される。
補足(なぜバイナリ互換が重要か): COM の呼び出しは
vtable(仮想関数テーブル)のオフセットで解決される。
既存メソッドの間に新しいメソッドを挿入すると、
再コンパイルしていない呼び出し側が別のメソッドを呼んでしまう。
だから「末尾への追加のみ許可」という制約になっている。VB 6.0 の「バイナリ互換」設定はこれを担保するための機能で、
保守で誤って「プロジェクト互換」に戻すと、
配布済みクライアントが動かなくなるという典型的な事故が起きる。
プロジェクト名.クラス名- 前述の
CreateObjectの引数に使用される。
- GUID
- COM オブジェクトを識別する
-
CoCreateInstanceの引数として渡される。
- GUID
- インターフェイスを識別する
-
CoCreateInstanceや、QueryInterfaceの引数として渡される。
HKEY_CLASSES_ROOT には、大きく分けて、
- 拡張子
- ProgID
- GUID
- CLSID
- IID
の3種類の情報があります。
- レジストリで、ProgID をたどると、サブキーに GUID がある場合があります。
- その場合は、さらにその GUID キーをたどると、COM 部品の情報があります。
COM 部品の実体は、レジストリの GUID の下、
-
InprocServer32の値を確認すると、どの dll ファイルが提供しているか分かります。 -
InprocServer32ではなくLocalServer32の値に書かれている場合もあります。
-
InprocServer32に書かれている場合
COM 部品を呼び出したプロセスと同じプロセスの中で動作する COM 部品。 -
LocalServer32に書かれている場合
COM 部品を呼び出したのとは別のプロセス内で動作し、
呼び出し元とはプロセス間通信して動作する COM 部品。
どちらも、COM ですが、使用方法としては同じです。
(デバッグやトラブルシュートでは、この違いは重要になってきますが)
補足(32bit / 64bit の落とし穴): レジストリの COM 登録は
32bit と 64bit で別の場所に書かれる。
プロセス 参照されるキー 64bit HKEY_CLASSES_ROOT\CLSID32bit(WOW64) HKEY_CLASSES_ROOT\Wow6432Node\CLSID「
regsvr32したのにCreateObjectが
80040154 (REGDB_E_CLASSNOTREG)で失敗する」というトラブルの多くは、
登録側と呼び出し側のビット数が食い違っていることが原因である。
C:\Windows\System32\regsvr32.exe(64bit)と
C:\Windows\SysWOW64\regsvr32.exe(32bit)を使い分ける必要がある
(紛らわしいが、SysWOW64の方が 32bit である)。
DCOM(Distributed COM)については、RPCを参照。
.NET からは COM 相互運用(COM Interop) で利用する。
| 方向 | 仕組み |
|---|---|
| .NET → COM |
RCW(Runtime Callable Wrapper)。Marshal.ReleaseComObject で明示解放できる |
| COM → .NET |
CCW(COM Callable Wrapper)。ComVisible 属性で公開 |
-
.NET Core 以降も Windows 上では COM Interop を利用できるが、
Windows 専用機能であり、
.NETのクロスプラットフォーム対応の対象外である。
- COM
http://www.kekyo.net/category/com- COM のアパートメント(連載)
Tags: 移行, Windows, プログラミング, .NET開発
このWikiは「Open棟梁Project」,「OSSコンソーシアム 開発基盤部会」によって運営されています。