Visual Basicは、Windows用アプリケーションをもっともスピーディーに開発できる開発ツールとして認知されている。しかし、さらに効率よくプログラミングするためには、あるいは設計をするためには、Visual BasicのベースとなっているWindows環境の理解がある程度は必要になる。Windowsに使われている様々な技術の中でも、ここではCOMについて解説する。COMの理解は、すでにWindowsアプリケーション開発者の必須項目である。
酒井 法雄
COMと言っても耳慣れない方も多いかもしれない。COMとは、Componet Object Modelの略で、その実体はOLE 2.0(Object Linking and Embedding)を動かすための基本的な仕組みのことである。つまり、COMはOLE 2.0と言い換えることもできるわけだ。
Visual Basicで使われているCOM技術はこれだけではない。カスタムコントロールもまたCOMベースである。以前のVisual Basicでは、VBXと呼ばれるVisual Basicのためのカスタムコントロールであったが、Visual Basic 4.0以降ではOCXと呼ばれるOLEベースのカスタムコントロールになっている。Visual Basic 5.0からは、これが多少仕組みを変えてActiveXコントロールと呼ばれるようになっている。
今や、カスタムコントロールなしでのアプリケーション開発は考えられないほどになっている。このダイアログからすべてのチェックを外してみると、図のようにごく基本的なコントロールしか使えなくなってしまう。これだけで多機能なアプリケーションを作るのは、カンタンとは言い難い。
このように、RAD(Rapid Application Development)としてのVisual Basicを支えているのは、COMベースのオブジェクトライブラリとカスタムコントロールである。これらがあってこそ、初めてVisual Basicを活かすことができるのである。
本来OLEは、Microsoft Power Pointで文字や図形を自由に貼り付けてデザインできるようにするために開発されたものである。したがって、WordにExcelの表を貼り付けるといったステレオタイプもあながち外れてはいない。しかし、OLE 2.0の仕様が発表になった数年前から、すでにOLEはそれだけの存在ではなくなっているのだ。
次に、DDE以降の歴史を追ってみよう。
この短い歴史の中で、まず注目したいのがDDEである。DDEは手動、自動、通知という3つのリンク形態を持ち、ソース(サーバー)側のデータをディスティネーション(クライアント)側にコピーして共有しようというものである。また、一時的にディスティネーション側データをソース側に転送することも可能である。さらに、ディスティネーション側からソース側にコマンド文字列を送信することもできた。これをうまく使えば、二つのアプリケーション間でデータのやり取りを比較的自由にプログラミングすることができたのである。
その後DDEML.DLLが提供されてAPIベースとなったものの、Windows 3.1自体がノンプリエンプティブなマルチタスクだったため、非同期で動作するDDEは、ドラッグやディスクアクセス、重い処理などが間に入ったときにリンクを保持し続けることができずに、うまく動作しないといった問題点が指摘された。
OLE 1.0は、DDEの手続きを簡略化し、もっと手軽にアプリケーションから使えるようにすることを目標とした。このため、あくまでも複合ドキュメントを主眼とし、データのファイルをサーバー側が管理するリンクと、クライアント側が管理するエンベッドの二つの方法が提供された。しかし、扱えるデータ型は相変わらずクリップボード形式のものであり、グローバルメモリのアドレスを使ってデータのやり取りをしており、64Kbytesの壁を越えられないというDDEそのままの制限があった。
OLE 2.0では、このような中途半端なOLE 1.0の仕様を抜本的に解決すべく、大幅な見直しが行われた。その主眼となる目標も複合ドキュメントの強化だけにとどまらず、ユーザーインターフェイスと操作性の改良、さらにはWindowsアプリケーション間での共通マクロとも言えるOLEオートメーションが掲げられた。結果的には、次のような改良が行われた。
ここでは、残念ながらこれらの一つ一つについて詳しく述べるページはないが、OLE 2.0はこれらの機能を実現するために、従来とはまったく違う構造を取っていることに着目してほしい。
OLE 2.0の中心となるのが、コンポーネントオブジェクトモデル、すなわちCOMである。ここでは、次の処理をする。
実際には、LRPCはインターフェイスと呼ばれる関数群をコールして実行される。サーバーオブジェクトには、あらかじめ自オブジェクト内のデータを操作するためのメソッド(メンバー関数)を用意しておく。COMではこれらのメソッドの一覧をvtableと呼ばれるテーブルに作成して、そのアドレスを管理する。クライアント側ではCOMを通してアクセス可能なメソッド一覧およびそのアドレスを知ることができる。そして、必要に応じてそのメソッドをプロシージャコールするわけだ。
このようなOLEのメカニズムのメリットを最大に活かしたのが、OLEオートメーションである。OLEオートメーションは、インターフェイス関数群をそのままサーバー側オブジェクトから公開された関数(いわゆるDLLでのエクスポートされた関数とは違う)と見なして呼び出すことができるようにしたものである。したがって、サーバーオブジェクトのプロパティやメソッドという形式を実現することができる。こうして、コンテナ(クライアント)アプリケーションからサーバーアプリケーションを操作することができるわけである。
ActiveXコントロールは内部的にも、もちろんOLE 2.0のインターフェイスを使うものであり、LRPCを使ったプロシージャコールでアクセスするものだ。したがって、ここでも従来のメッセージベースだったVBXでの制限を克服できるようになっている。また、プロシージャをコールするという形式が標準であることから、メソッドをカスタマイズすることができる。これも、従来のVBXではできなかったことだ。
OLEコントロールで注意しておきたいのは、通常のOLEサーバーより高速に動作するという点だ。実は、OLEサーバーには二つの種類がある。一つはアウトオブプロセスOLEサーバーであり、もう一つはインプロセスOLEサーバーである。
概念的な話はこれくらいにして、Visual BasicでのCOMプログラミングについて考えてみよう。COMといっても、すでに述べたことから分かるように、大きく分けると二つのものがある。
この引数で、どのボタンかを知ることができるハズだが、「Button As Button」というのはどういう意味がさっぱり分からない。実は、これはButtonという仮引数名のButton型オブジェクトという意味である。つまり、ツールバー上に配置されたボタンは、それぞれがオブジェクトとして扱われるのである。通常は、ButtonオブジェクトのKeyプロパティの内容などを見て、何のボタンかを判断するのだ。
ここでは、オブジェクト変数objに、CreateObject関数を使ってExcelのSheetオブジェクトを作っている。したがって、objはSheetオブジェクトになる。そのシート内にあるセル(1, 1)の値だから、最後の行のようになるわけだ。
objは、Sheetオブジェクトであることに変わりはない。しかし、SheetはExcelという大きなアプリケーションの一部に過ぎない。幸いなことに、Sheetオブジェクトには、このアプリケーション自体を示すApplicationオブジェクトがある。つまり、次の行まででExcelのアプリケーション自体のオブジェクトを示すことになるのだ。
さらにobj.Applicationから順次見ていれば、次表のようになる。
このように、オブジェクトは往々にして親子関係や兄弟関係があり、兄弟は複数いてコレクションになっていたりする。ExcelにしてもDAOにしても、このような関係がどうなっているかを示す図があるのがふつうである。これをよく見てプログラミングしていく必要がある。
Visual Basic 4.0から増えた重要な機能として、OLEサーバーを作る機能がある。OLEサーバーと言っても、Excelのようにコンテナ内に表示されてビジュアルエディッティングできるというものではない。ただライブラリのようにして呼び出すものだ。実際にはフォームなどと組み合わせることもできるが、別ウィンドウになってしまう。方向性としては、コーディング主体のライブラリを作るものである。
また、ひとつのクラスから別のクラスをインスタンシングするといった作り方をすれば、オブジェクトの親子関係を作ることができる。コレクションもCollectionオブジェクトを使って作ることができるから、兄弟関係も作ることができる。つまり、DAOやExcelのような複雑なオブジェクトの親子関係も作ることができるわけだ。
ところで、実際にOLEサーバーを作るということは、プロパティ、メソッド、イベントを実装することである。それぞれは、次のようにして作ることができる。
プロパティは、次の2つのいずれかで作ることができる。
PublicなSubまたはFunctionプロシージャは、そのままメソッドになる。
クラスのイベントは、Visual Basic 5.0から利用できるようになった機能だ。これはクライアント側の設定も絡むので、それぞれについて説明しよう。
イベントのプロトタイプを、記述する。先頭は、Public Eventで始まり、イベント名および引数名とそのデータ型を記述する。
イベントを呼び出したい位置で、RaiseEvent文を使ってイベントをコールする。このとき、引数があれば同時に指定する。
Visual Basicのライブラリとしてのオブジェクトは、参照設定してあれば、まるで最初からVisual Basicの言語仕様にななっているかのように使うことができる。このようなものは、アーリーバインドと呼ばれるものだ。参照設定がされている時点で、オブジェクトのクラス名は言語仕様のように使うことができるのである。これにも厳密には2つの方法がある。
ポイントは、Newというキーワードを使うことだ。これは、Set文を使って次のように二つに分割することもできる。
ちなみに、オブジェクト変数の解放は、NothingをSetする。
レジストリデータベースは、従来の16bit WindowsのWIN.INIやSYSTEM.INIの代わりのものとしても使われている。また、デスクトップを右クリックしたときにも参照される。ものによっては、その時点で特定のOLEサーバーが起動したりする。
すでに述べたように、ユーザーインターフェイスを持つ特殊なオブジェクトが、ActiveXコントロールである。
OLEがCOMと呼ばれるようになった背景にあるのは、COMの分散コンピューティング版であるDCOM(Distributed COM)である。Microsoftは従来はこれをネットワークOLEと呼んでいた。これが、分散オブジェクトの仕様ばかりを決めていたCORBAという団体に関連するベンダーたちが、SOM、DSOMといった名前を使ったものだから、MicrosoftはCOM、DCOMという名前にしたのであろう。
実は、Visual Basic 4.0にも似たような仕組みとして、リモートオートメーションがあった。これは、OLEのコンテナとサーバーの間にちょっと細工をして、特定のレジストリエントリのものだけは外部のコンピュータ上にあるOLEサーバーを実行させようというものである。DCOMはこれとよく似た仕組みだが、実現方法や管理方法が少々異なっている。しかし、できることは基本的には同じであると考えればよい。
では、他のマシンにあるOLEサーバーを使ってどんないいことがあるかというと、ひとつは水平分散処理によるパフォーマンスやスケーラビリティの向上である。同じ処理を複数のマシンに分散して行えば、その分だけいろいろなメリットが出てくる。逆に複数マシンに分散したオブジェクトの管理などの面では複雑化する部分も出てくる。残念ながら現状では、このデメリットを克服し実用レベルに達するほどのノウハウや手法が確立されているとは言えない。
そこへきたのがインターネットブーム、そしてイントラネットブームである。
しかし、世の中そんなにうまい話ばかりではない。実際には細かい動作やインターフェイスをHTMLだけで実現するのは難しく、JavaやJava Script、MicrosoftからはActiveXコントロールとVBScriptを組み合わせて、よりアプリケーションらしい動きをさせようということになってきた。
このように、COMはDCOMとなり、すでに分散コンピューティングの世界に突入しつつある。しかし、これはActiveX技術と組み合わせたイントラネット向きの技術というより、分散コンピューティングの基礎となる仕組みである。MicrosoftはActive Directory構想を発表し、あくまでも本筋は分散コンピューティングであるとアピールした。この方向は正しいと思う。イントラネットなどではすでにさまざまなアーキテクチャーを組み合わせて実現する必要がでてきている。それでも問題が出るために、しょっちゅう新しい技術が追加されている。これでは開発効率を下げこそすれ、上げることはない。
OLEというと、どうしてもWordにExcelの表を貼り付けるといったステレオタイプを連想してしまいがちである。そこで、Microsoftは従来はOLE 2.0と呼んでいたものを、そのベースとなるアーキテクチャーのCOMと呼ぶようになったのである。
しかし、先に述べたような連想からすると、Visual Basicを理解しもう一歩先に進むために、どうしてCOMが必要なのかが分からない。単にアプリケーション間でのデータ共有にすぎないのではないかと思えてくるからである。
しかし、データ共有をどのようにして実現しているかが重要なのだ。実は、COMではプロセス間通信を使ってデータを共有している。プロセス間通信は通信であるから、データ共有以外の目的にも使えるわけである。そして、現実にVisual Basic 4.0からは、その開発環境にもCOMは積極的に取り入れられている。
たとえば、Visual Basicの参照設定ダイアログ(図)を出してみると、「参照可能なライブラリファイル」の一覧が得られる。どのようなものがあるかざっと眺めてみると、データアクセスをするためのDAO Object Libraryや、カスタムコントロール用のライブラリ、さらにはアドインなどがあることが分かる。これらは、今や大変大きく高性能になってしまったVisual Basicを支えるライブラリである。たとえば、DAOのライブラリを参照していなければ、データアクセスの機能は使うことができない。Visual Basicでは、データアクセスの言語仕様があたかも内蔵されているように見えるが、実際には外部にあるライブラリである。実際のところ、これはAccessと共通のものである。
そればかりではない。Visual Basic For ApplicationsやVisual Basic Objects and proceduresといったものまである。これらはVisual Basicで最低限のプログラムが実行できるようにするためのものである。
この参照設定で得られるライブラリこそ、OLEサーバーなのである。つまり、Visual BasicはすでにCOMを使っているのだ。逆の言い方をすれば、COMがなければVisual Basic自体が動かないということになってしまう。
Visual Basicのカスタムコントロール一覧(図)として出てくるものは、いわゆるOCXばかりではない。ExcelなどのOLEサーバーもカスタムコントロールのように扱うことができるようになっている。
図3:すべてのチェックをはずすと
Visual Basic 4.0からは、OLEサーバーを作る機能が増えている。これに加えて、Visual Basic 5.0からはActiveXコントロールも作ることができるようになっている。今まではライブラリを使うことばかり考えていればよかったが、今後はライブラリやカスタムコントロールを作り、それを資産として後からも活用できるようなプログラミングスタイルを考えなくてはならない。そうしてこそ、開発の効率を上げることができるのである。
ここでは、まずCOMのおおまかな内部動作を述べてから、Visual BasicでのOLE ServerやActiveXコントロールの作成法、そしてどうしたら効率よくプログラミングができるかを考えていきたい。
OLEはプロセス間通信の一つの形式である。こう捉えると、その存在価値もかなり違って見えるはずだ。
Windowsでのプロセス間通信(厳密には、Windows 3.1まではプロセスとは言わなかったが)の歴史を振り返ると、その後のプロセス間通信のベースとなるクリップボードからスタートし、メッセージベースDDE(Dynamic Data Exchange)、APIベースのDDE、そしてOLEという流れがある。
一方、ファイルマネージャからプログラムマネージャに選択したファイル情報を送るドラッグ&ドロップという便利なインターフェイスがある。このインターフェイス自体はプロセス間通信とは言うには語弊があるものの、結果的に似たようなものになっている。これらを統合した形で出てきたのが、OLE 2.0(図4)である。もっとも、今となってはすでにOLEといえば2.0のことを指すのが当然になっており、さらに最近はCOMと呼ぶようになっている。
しかし、当初のDDEは非同期で動作するメッセージベースだったため、プログラム中で非同期に対応した処理を矛盾なくコーディングするのが難しかった。
それもそのはず、実はOLEのデータのやり取りをする中心となるOLECLI.DLLとOLESVR.DLLの間はあくまでも非同期のDDEが使われていたのである。また、DDEのメリットだったコマンド文字列の送信などはほとんど使われない仕様となった。
さらに、インプレイスアクティべーションでサーバーでの編集画面をコンテナ内部に表示し、サーバー側で発生したイベントをコンテナ側に通知するイベントのメカニズムを装備したのがOLEベースのカスタムコントロール、いわゆるActiveXコントロールである。このイベント通知のメカニズムは、実はOLEのコンテナとサーバーが逆転したような形で実現される。つまり、通常ならばサーバーが公開しているメソッドをコンテナが呼び出すのだが、イベントではコンテナが公開しているメソッドをサーバーが呼び出し、これがイベントとしてコンテナ側に認識される。ちなみに、Visual Basic 4.0でも、同様の手法で非同期通知処理を実現することができた。
すでに述べたように、Visual BasicのライブラリはOLEサーバーとして、カスタムコントロールはOLEコントロールとして実現されている。関数形式での通信ができるため、プロセス間通信でもVisual Basicという言語がそのまま使えるというわけだ。
アウトオブプロセスOLEサーバーは通常EXE形式の実行ファイルであり、動作は通常のOLE 2.0のインターフェイスである。つまり、コンテナ側から見たら外にある別プロセスで動作しているサーバーである。
一方、インプロセスOLEサーバーは、コンテナが動作してるプロセスの内部にロードされて実行されるもので、通常はDLL形式のものである。インプロセスOLEサーバーのときにも、もちろんOLEのインターフェイスが使われるが、内部的に見るとスタック呼び出しの形でプロシージャをコールしている。したがって、実際にはプロセス間通信はしていないから、マーシャリングによるオーバーヘッドは軽減される。このため、アウトオブプロセスOLEサーバーに比較して、数百倍は高速に呼び出すことが可能である。Visual Basicのライブラリ、すなわちDAOやRDOなど、さらにはOLEベースのミドルウェアOracle Objects OLEも、このインプロセスOLEサーバーである。
OLEコントロールは、独立したアプリケーションではないから、実際にはDLL形式のOLEサーバー、すなわちインプロセスOLEサーバーになる。このため、高速にプロシージャコールをすることが可能なのである。
Visual Basic 4.0では、OLEサーバーをEXE形式として作ればアウトオブプロセスになるし、DLL形式として作ればインプロセスになる。
インプロセスOLEサーバーの方が高速でよいようにも思えるが、実際には必ずしもそうではない。というのも、インプロセスでは同じプロセスで動くから、致命的なエラーが発生したとき、呼び出し元のコンテナまで汚染されてしまい、まとめてプロセスがなくなってしまうことがあるからだ。
ひとつはWordにExcelの表を貼り付けるといったもので、これは最終的にひとつのドキュメントを作ることを目標としている。いわゆるドキュメント指向と呼ばれるものだ。
もう一つは、OLE Automationを活用して、ライブラリやカスタムコントロールといったコンポーネントを組み合わせてプログラミングしようというものだ。これは、コンポーネント指向と呼ばれる。
いずれのものも、生産性を上げるために役割を分けた部品を使おうという方向は同じである。
我々がVisual Basicを使ってプログラミングしようというときに重要なのは、後者である。となると、OLE Automationについて、サーバー側およびクライアント側の使い方を知るということが重要になる。
これは何もOLEサーバーを作らなくてはならないということではない。まずは既存のCOMベースのライブラリの使い方に慣れよう。たとえば、データアクセスのためのDAO(Data Access Objects)やRDO(Remote Data Objects)などは、まさにその名前の通りオブジェクトである。
オブジェクトというと何だか難しい感じがするが、ユーザーインターフェイスを持たない目に見えないコントロールだと思えばよい。オブジェクトにはVisual Basic 4.0まではイベントもなかったが、Visual Basic 5.0からはイベントも使えるようになった。本当に目に見えないコントロールなのである。いや、オブジェクトという大きなくくりの中で、目に見えるものがコントロールと呼ばれる特殊なものだと考えた方がよいかもしれない。
目に見えない、すなわちプロパティウィンドウに出てこないものであるから、デザイン時にはテストすることができない。つまり、どうしてもコードを書いて実行して動作を確認しなくてはならないところが、オブジェクトに馴染みにくい要因である。
しかし、DAOを使えばDataコントロールなどを使うよりずっと細かい処理を書ける。また、コントロールだけ使おうとしても、すでにオブジェクトの知識がないと使えないコントロールもある。
たとえば、ToolBarコントロールを考えてみよう。このコントロールはImageListと組み合わせて使うものだが、ツールバーにあるどのボタンが押されかを知るには、どうしたらよいだろうか。ToolBarコントロールをダブルクリックしてコードを出してみると、次のようなイベントプロシージャが出てくる。
このように、すでにコントロールを使うだけでもオブジェクトという考え方をしていかなくてはならない。と言っても、実際問題としては、特に難しいことはない。コントロールだって使いこなすためには、プロパティウィンドウに出ていないプロパティや、メソッドなどを駆使しなくてはならないのである。そう考えれば、オブジェクトだからといって特別に難しいなどと感じる必要はないのである。
しかし、コントロールと少々違っているのは、コレクションを積極的に使わなくてはならないところだ。コレクションとは、オブジェクトの集合である。DAOのことを考えてみよう。ひとつのデータベースファイルには、複数のテーブルオブジェクトがあり、その中には複数のフィールドオブジェクトがある。このように複数のオブジェクトはいくつあるか分からない。このようなときには、複数のオブジェクトをまとめたものとして考え、個々には、配列と同じように番号でアクセスできたり、連想配列のように名前を使ってアクセスできた方がよい。このような考え方をコレクションと言う。
先ほどのツールバーの例を考えれば、ツールバーというオブジェクトの中には、Buttonオブジェクトが複数入っている。これらをまとめて扱うに、複数形のsをつけたButtonsコレクションがあるわけだ。
DAOでもそうだが、オブジェクトの下にオブジェクトがあるという階層構造になっていることもある。
Visual BasicではOLE Automationを使ってExcelを扱うこともできるが、これも階層構造になっている。Excelはご存じの通り、ひとつのMDIアプリケーションである。各子ウィンドウはワークブックと呼ばれ、その中にはワークシートやチャート、ダイアログといったものを表示することができる。その中のワークシートを考えてみれば、行と列があり、そこから指定したセルの値や表示形式などを個々に決めることもできる。Visual BasicからOLEオートメーションを使って、Excelのワークシートの特定位置(1, 1)のセルの値は、次のように表すことができる。
Dim obj As Object
Set obj = CreateObject("Excel.Sheet")
Text1.Text = obj.Cells(1, 1).Value
しかし、最後の行は次のように書き直すこともできる。
Text1.Text = obj.Application.Workbooks(1).WorkSheets("Sheet1").Cells(1, 1).Value
obj.Application
Workbooks(1) Workbooksコレクションの1番目のオブジェクト、
すなわちMDI子ウィンドウのひとつWorkSheets("Sheet1") WorkSheetsコレクションの”Sheet1”という名前のワークシート Cells(1, 1) (1, 1)にあるセル Value セルの値
というのも、後述するリモートオートメーションと組み合わせて、分散コンピューティングのビジネスルール層のライブラリとして使おうというものだからだ。ネットワークに接続されたOLEサーバーにユーザーインターフェイスがあっても役に立たないし、逆に誤って操作される可能性が出てくる。したがって、ユーザーインターフェイスを持たせない方がよいのである。
Visual BasicからOLEサーバーを作るときには、Classモジュールを使う。プロジェクトの名前とClassモジュールのNameプロパティの組み合わせで、OLEサーバーのクラス名が決定する。つまり、Visual BasicのClassはオブジェクト指向のクラスではなく、OLEのクラスなのである。
Visual BasicのClassの機能でも、C++などのオブジェクト指向言語のようにクラスを作り、それをインスタンシングして単純なライブラリではない使い方はできる。しかし、クラスの継承やオーバーライドの仕組みはない。
つまり、本当の意味でのオブジェクト指向的に使うのではなく、クラスを元にしたOLEサーバーを作り、それをコンポーネントとして再利用していこうというものなのである。
OLEサーバーは、先に述べたインプロセスとアウトオブプロセスの他に、Instancingプロパティで動作を変えることができる。具体的には、ひとつのOLEサーバーが複数のコンテナの相手をするMultiUseか、ひとつのOLEサーバーがひとつのコンテナを相手する、すなわち複数のコンテナごとに対応したOLEサーバーがそれぞれ起動されるSingle Useがある。OLEでは、LRPCによる呼び出しはキューに溜まるので、Multi Useでは複数のコンテナからリクエストがあったとき、キューに入った順に処理していかなければならない。一方Single Useのときには、キューに入って待たされることはMulti Useより断然少なくなるわけだから、パフォーマンスは向上する。
ただし、その分メモリを使うことになるわけだから、現実的には使うことができるメモリサイズによってパフォーマンスは左右されることになる。ちなみに、インプロセスのときには、Multi Useでも当然ながらコンテナごとに複数のOLEサーバーが起動することになる。
しかし、ひとつのコンテナから複数のオブジェクトが作られるときには、そのひとつのOLEサーバーが相手をすることになる。つまり、インプロセスのときSingleUseはあり得ないということだ。
さて、ここから先は、実際のOLEサーバーの作り方の話をしたいところなのだが、これにはかなり多くのトピックがある。すでに私は過去に本誌でこうしたテーマで記事を書いているし、発表されたばかりのVisual Basic 5.0の仕様を見ると、このあたりはかなり変わっている部分がありそうだ。まだ記事として公開できるVisual Basicは提供されていない現状では、中途半端な内容しか書くことができない。そこで、今回はこのあたりはさっくりと省略させていただきたい。今回は実質的なコーディングよりも、その影に隠れがちな仕組みやトピックといったあたりを中心にしたい。Visual Basic 5.0でのOLEサーバーについては、実際のコーディングが可能になった時点で、あらためて紹介したい。
例: Public Function Func(x1 As Integer) As String
例
Public Event evt(ByVal xx As Integer, ByVal When As Date)
例
RaiseEvent evt(x, Now)
例
Dim WithEvents obj As ObjName
ひとつは、次のように一行でオブジェクト変数の宣言と、インスタンシングをしてしまう方法だ。
Dim obj As New Class1
Dim obj As Class1
Set obj = New Class1
Set obj = Nothing
この方法は、プログラム中にコードで直接OLEのクラス名が書いてある。リテラル文字列にはなっていないことに注意してほしい。
一方、実行時にオブジェクト名を自由に指定できるのが、レイトバインドと呼ばれる方法で、すでに先ほども例を示したが次のように書くことができる。
Dim obj As Object
Set obj = CreateObject(“Project1.Class1”)
このように、プロジェクト名とClass名を使ってオブジェクトを作ることができる。
念のために、クラスとオブジェクトのことを言っておくと、クラスとはそのままでは実行できないものである。言わばタイヤキの型である。実際にクラスを使うためには、タイヤキの型に小麦粉やアンコを流し込んで焼かなくてはならない。これをインスタンス化あるいはインスタンシングと呼ぶ。ここで、ひとつの型から複数のタイヤキを作ることができることに注目してほしい。このひとつひとつのタイヤキがインスタンスである。これは、メモ帳のように、ひとつのEXEファイルから複数のアプリケーション(ウィンドウ)を起動できることに似ている。インスタンシングされて食べることができるようになったタイヤキを、オブジェクトと呼ぶのである。
レイトバインドは、OLEのクラス名を元にして、実行時にオブジェクトをインスタンシング化しなくてはならない。そのため、あらかじめ参照設定してあり、OLEのクラス名の名前解決がされてインスタンシングされているアーリーバインドに比較して、実行速度が遅くなる。
参照設定ダイアログには、OLEサーバーのクラス名の一覧が出てくる。また、CreateObjectをしたときにも、OLEサーバーのクラス名を指定する。このように、OLEではクラス名を指定するだけで、オブジェクトを区別することができる。しかし、これはちょっと妙ではないか。オブジェクトの名前だけで実体となるEXEやDLLの場所をどうやって解決しているのだろうか。実は、これにはレジストリデータベースが使われている。
Windowsでは、REGEDIT.EXEあるいはREGEDT32.EXEというレジストリエディタアプリケーションが含まれている。これはレジストリデータベースの内容を修正することができるものだが、レジストリについての十分な知識がないまま使うと、システム自体がちゃんと動かなくなる危険性がある。このため、スタートメニューなどには登録されていない。
レジストリデータベースを起動してみると、図のようにツリー状にデータが含まれている。この中に、クラス名とそれに対応したユニークな番号、実体のファイルのある場所、バージョンなどの情報が格納されている。COMはインスタンシング時にこれらのデータベースを参照して、適切なファイルを探し出すのである。ここで重要なのは、クラス名に対応したユニークな番号である。これをクラスIDと呼んでいる。
クラス名では万が一同じものになる可能性もあるが、クラスIDは絶対にユニークになるようになっている。というのも、MACアドレスと呼ばれるイーサネットカードにあるユニークな番号を組み合わせてクラスIDは決められているからである。
もっとも、マシンのOSをインストールしなおしたり、ちょっと手を加えればクラスIDが変えられたり、同じIDを作ることは可能ではあるだろう。
Windowsのシステムがだんだん重くなっていくのは、このレジストリデータベースが巨大化してくることに原因がある場合も少なくない。また、デバッグ時などにやたらにOLEサーバーを作っていくと、レジストリデータベースが巨大かつめちゃくちゃになってしまうこともある。開発用マシンは、定期的にインストールしなおす、レジストリファイルのバックアップをとっておくなどの対策をした方がよいだろう。
Visual Basic 5.0からは、ActiveXコントロールを作ることができるようになっている。この方法については、Visual Basic 5.0 CCE(Control Creation Edition)を使った記事をすでに前々号と前号に執筆したので、そちらをご参照いただきたい。
基本的には、フォームのようなユーザーインターフェイスを持つClassモジュールともいえる。
UserControlモジュールを使い、プログラミングしていけばよい。ちょっと注意しないといけないのは、ActiveXコントロールはデザイン時にもプロパティウィンドウやプロパティシートとのやりとりや、デザイン時のリサイズなどに対応した処理が要求されるということだ。
ライブラリは通常のOLEサーバー、ユーザーインターフェイスを持つ部品はActiveXコントロールとして部品化していくのがよいだろう。
ここで、あえて述べておくと、ActiveXと言う名前からついインターネットやイントラネットに使われるものというイメージがあるかもしれない。実際にはそんなことはなく、よく使う処理を部品化するための便利な仕組みが増えたと考えた方が妥当である。もちろん、インターネットなどにも使えるわけであるが、これはしょせん色物である。本来、COMはインターネットのためのものではなく、分散コンピューティングのための布石なのだ。
DCOMは、すでにWindows NT 4.0に搭載されており、Windows95版もβが出ている。DCOMの管理はレジストリをいじるものであるから、やはりスタートメニューからはたどれないDCOMCNFG.EXEで管理する。このツールでは、各OLEサーバーについて、セキュリティや実行するコンピュータ、権限などを細かく設定できるようになっている。
しかし、コンテナとなるクライアントでは基本的なユーザーインターフェイスだけを持ち、ビジネスルールをOLEサーバー化し、さらにそこからデータアクセスするという、いわゆる3階層モデルを実現すれば、クライアント側のインストールなどの管理はしやすくなるし、メンテナンスも1か所の修正で済むようになる。
WWWすなわちHTTPを使ったシステムでは、クライアントは単なるWebブラウザである。サーバーの仕組みさえ作り込めば、似たような3階層システムを構築できる。さらにサーバーで管理は一括できるのだから、これはコストも削減できる。
だが、本当に問題だったのはそんなことではなかった。WWWで使われているHTTPは非常に単純なプロトコルだ。サーバー側にデータを送るようにリクエストすると、対応するデータを送りつけるというだけだ。つまり、セッションはそれだけで切れてしまうのである。ということは、データアクセスなどで必要になるトランザクション処理などは実現できないということになる。
そこで、HTTPとは別セッションでデータアクセスができるようにしようという話になったわけだ。HTTPをベースとするブラウザでそれ以外のプロトコルを併用するというのもおかしな話だが、JavaやActiveXコントロールはそれを可能にした。たとえば、図のような形でブラウザ状で動作しているActiveXコントロールがDCOMを使ってサーバー側と通信をするのである。OLEサーバー側に含まれているルーチンで、データアクセスをして、必要な結果だけをブラウザに返せるようにすればよいわけだ。また、トランザクションだけでなく、ページを変えなくてもインタラクティブに操作ができるようになるのも大きなメリットだ。
もっとまとまった技術で同じシステムを作ることを考えるらば、イントラネットなどと妙なことを言わずに、従来のC/S型にするか、ActiveX DocumentsでアプリケーションがそのままWebページに表示されるようにした方がよい。
何にしても、DCOMはイントラネットを構築したり、分散処理システムを作るのには使いやすいシステムである。
ざっとCOMについて述べてきたが、本来これは膨大な量の内容である。とても数ページで語れるものではない。しかし、その概要や使うためのポイントなどの基礎知識は一通り書いたつもりだ。Visual Basic 5.0が発売された後、新しい使いこなしのポイントなどを順次説明することにしよう。