Chapter.20

アウトプロセスサーバ(1)


1.アウトプロセスサーバ

リンクコンテナの前に完全な埋め込みコンテナの実装を解説するのが先だなと思いつつ、今回はアウトプロセスサーバについて解説します。

アセンブリをREGASM.EXEを使用してCOM公開した場合、例え実行ファイルがEXE形式であったとしても、常にインプロセスサーバとして動作します。ほとんどのケースでこれは問題にならないと思いますが、コンポーネントをサービスとして実装したい場合やクライアントとは独立したUIを実装したい場合等には、これを使用することはできません。アセンブリをアウトプロセスサーバとして動作させるには、起動したプロセスからSystem.Runtime.InteropServices.RegistrationServices.RegisterTypeForComClientsメソッドを呼び出すことで可能です。

上記以外に解決しなければならない課題として、レジストリへの登録とマーシャリングという二つの問題が存在しています。めんどくさいので、マーシャリングについては、ここでは特に解説しません。
アセンブリをアウトプロセスサーバとして動作させるためのレジストリエントリを登録する方法は、大きく分けて二つあります。REGASM.EXEを使用する方法と独自に実装する方法です。REGASM.EXEを使用すると、インプロセスサーバ用の設定が登録された後、System.Runtime.InteropServices.ComRegisterFunctionAttribute属性を持ったメソッドが呼び出されます。このメソッド内で、アウトプロセスサーバ用設定を追加し、インプロセスサーバ用設定を削除すれば、アウトプロセスサーバとして動作することが可能となります。ただし、インプロセスサーバを使用しないクライアントが対象であれば、インプロセスサーバ用の設定を削除する必要はありません。


2.サンプル

今回のサンプルを作成する上で一番苦労したのは、アウトプロセスサーバを利用可能なクライアントを探すことでした。結局、それなりに動作してコード量が少なくて済みそうなPHPデバッガ(http://dd.cron.ru/dbg/)に落ち着きました。リンク先URLを読んでいただければ分かると思いますが、デバッガとのインターフェースをCOM公開することにより、独自のデバッガを制作することが可能となっています。例によってVB.NETとC#でサンプルソースを用意しました。

VB.NETサンプルソース:chap20.vb.lzh (36KB 2007/1/28)
C#サンプルソース:chap20.cs.lzh (36KB 2007/1/28)

サンプルを実行するための環境構成方法は以下の通りです。
  1. PHPの実行環境を構成します。私はローカルPC上のIISで動作するように構成しました。
  2. ダウンロードページ(http://dd.cron.ru/dbg/downloads.php)から DBG x.x.x dbglistner(dbg-x.x.x-cli-w32.zip) と DBG x.x.x dbg modules(dbg-x.x.x-win32.zip) をダウンロードします。
  3. DBG x.x.x dbg modules(dbg-x.x.x-win32.zip) をPHPエクステンションとしてインストールします。インストールに成功するとphpinfoページには以下のようなセクションが追加されます。
    phpifo DBGセクション
  4. php.iniに以下の内容を書き足し、JITデバッグを有効にします。
    [Debugger]
    debugger.enabled = On
    debugger.JIT_enabled = On

    書き足した後、JITデバッグが有効になっているかどうかをphpinfoページを見て確認してください。
  5. DBG x.x.x dbglistner(dbg-x.x.x-cli-w32.zip) を任意のフォルダに展開し、register.batを実行します。これによりリスナー(DbgListener.exe)とプロキシ/スタブDLL(PHPDbgPS.dll)がレジストリに登録されます。
  6. サンプルをビルドします。ビルド方法は今までのサンプルと同様です。
  7. 以下のようにコマンドを入力し、ビルドしたサンプルをレジストリに登録します。
    chap20.exe /RegServer
  8. リスナー(DbgListener.exe)を起動してタスクトレイからSetup画面を表示し、IDE COM classの設定を変更します。以下のようにChap20を選択することができれば、サンプルのレジストリ登録は成功しています。
    リスナー設定画面
    この操作を行いダイアログを閉じた後も、リスナー(DbgListener.exe)は起動しておいてください。
  9. サンプルに添付しているtest.phpをWEBサーバに配置して実行します。実行時に以下のような画面が表示されれば、実行環境の構成は正常に完了しています。
    実行画面
このPHPデバッグ環境の構成が本サンプルで最も難しいところでしょう。まぁ、コマンドラインによるビルドを前提としているサンプルを試そうとする猛者には大したことではないかもしれませんが・・・。

リスナーは特定のコンポーネントカテゴリ(CATID_PHPDBG)をインプリメントしているサーバを検索してIDE COM classのコンボボックスに表示していると考えられます。今回のサンプルではコンポーネントカテゴリの操作のために、ICatRegisterインターフェースを使用しています。

リスナーにデバッグセッションを直接開始するという機能があったので、それを使用してみました。プロセスの起動引数にURLを直接渡すことにより、PHPスクリプトの先頭からデバッグを開始することができます。ただし、Windows XP Professional環境でデバッグを直接開始した時にスクリプトエラーが発生すると、リスナーからエラーが返却されデバッグが中断します。Windows Server 2003環境では発生しないため、どこかに何らかの問題があると考えていますが、解決には至っていません。

なお、.NET Framework 2.0では、System.Runtime.InteropServices.RegistrationServices.RegisterTypeForComClientsメソッドはオーバーロードされており、より使い易いメソッドが追加されています。さらにCOM公開するクラスの基本クラス用に、System.Runtime.InteropServices.StandardOleMarshalObjectが追加されており、.NET Frameworkのランタイムをバージョンアップしたい気にさせてくれます。


3.まとめ

今までのコンテンツを読み返すと、「3.まとめ」の部分には感想が述べられているだけで、あまりまとまっているようには見えません。とりあえずまとめてみると、アウトプロセスサーバを作成するポイントは次の3点になると思います。
System.Runtime.InteropServices.RegistrationServices.RegisterTypeForComClientsメソッドを使用すること
・レジストリへの登録は処理の一部(もしくは全部)をコーディングすること
・なるべく、.NET Framework 2.0を使用すること

今回のサンプルで最も苦労したのは、PHPでランタイムエラーを発生させる方法を探すことでした。PHPの言語仕様を知っていれば、あまり苦労しなかったと思いますが・・・。なお、コンパイルエラーを発生させても、JITデバッガは起動できませんでした。

最後に、次回からは完全な埋め込みコンテナの実装を解説していきたいと思います。


前へ 次へ
OLE on .NET Frameworkへ
総合トップへ

サンプルで使用しているキーワード
CLSID_StdComponentCategoriesMgr ICatRegiter System.Runtime.InteropServices.RegistrationServices.RegisterTypeForComClients