プロジェクトオプションを変更して、一度クラスライブラリを生成してからレジストリに登録されている値を比較してみたところ、クラスライブラリのほうは CodeBase というキーに生成した dll のパスが入っていて、どうもこれが exe の時に設定されていなかったために WSH で CreateObject した時にファイルが無いといったエラーが出ていたようです。……たぶん。
アセンブリが見つからなかった場合は、Mainメソッドの1行目(new Util())で“System.IO.FileNotFoundException”が発生することになる。
ただ GAC に登録してもやっぱり同じエラーが出ていたのがちょっと気になりますが。そもそも Regasm やら GAC やらに exe を突っ込んで良いものかもさっぱりわからないし (その辺の記述が全然見つからない)。まあしかし、 CodeBase を登録したらとりあえず動いたので良しとします。仕事で使うんならこんないい加減なことは許されないところですけども、まあまだ暇潰しの範疇なので。
とりあえず以下に覚書としてまとめておきます。環境は Visual Studio 2005 Express Edition(C#) です。
やりたいこと
C# で作成したアプリケーション (EXE) の内部で定義しているクラスを外部に公開したい。いわゆるオートメーション API というやつでしょうか? Office 製品 (Word とか Excel) とかでやっているやつですが、そんなのを .NET Framework の COM 相互運用機能を用いてできないかな、っていう、そういう試みです。
プロジェクトを作成する
まずプロジェクトを作成します。「新しいプロジェクトを作成する」から「Windows アプリケーション」を選択します。ソースには一切手を入れる必要はありません。
プロジェクトオプションを変更
プロジェクトのプロパティを開き、以下の設定を変更します。
まず「アプリケーション」タブの「アセンブリ情報」ボタンをクリックして表示されるダイアログにある「アセンブリを COM 参照可能にする」のチェックを有効にします。
次に「署名」タブの「アセンブリの署名」のチェックを有効にし、「キーファイル」コンボボックスから「新規作成」を選択します。ダイアログが表示されるので、「キーファイル」の欄に好きなファイル名を入力します。自分は SampleApp.snk としました (プロジェクトファイルが SampleApp なので合わせました) 。パスワードは、とりあえず無しにしました。
プロジェクトをビルド
設定が完了したらビルドします。 F6 で一発。
レジストリにアプリケーションを登録
できあがった exe をレジストリに登録します。これには Regasm.exe を使用します。これは自分の環境では「C:/WINDOWS/Microsoft.NET/Framework/v2.0.50727」に入っていました。
Regasm.exe /tlb /codebase SampleApp.exe
/tlb はタイプライブラリを生成するオプションで、 /codebase は実行ファイルのパスをレジストリに登録するのに使います。 SampleApp.exe はビルドしてできた実行ファイルのファイル名になるので、任意の名称に変更してください。
これで一通りの設定は完了です。
使ってみる
これで外部から好き放題アプリケーション内部で定義されているクラスをオブジェクトとして触れるようになったので、ためしに VBScript を使って呼び出してみます。
Set obj = CreateObject("SampleApp.Form1") obj.ShowDialog()
CreateObject 関数でクラスを生成しています。引数にはクラスの名前を指定しますが、これは「名前空間.クラス名」といった文字列になります。自動生成したクラスなので名前は Form1 のままです。
で、取得したオブジェクトの ShowDialog メソッドを呼び出しています。これは Form クラスにもともとに定義されているメソッドで、ウィンドウをモーダルなダイアログとして表示するものです。
これをたとえば Sample.vbs という名前で保存して、エクスプローラからダブルクリックして実行すると、 Form1 の画面が表示されます。
上の画像はコマンドプロンプトから実行した例です。コマンドプロンプトの横に表示されているのが、 VBScript から起動したウィンドウです。やたら苦労したので面倒だなと思ったりしたけど、こう書いてしまうととても簡単だなあ。 C# まんせーですね。
ということで思い付きで始めた C# で EXE サーバ計画もひと段落です。これで全てうまくいくのかも、そもそもこのやり方が正しいのかもわからないけれど、まあ、遊ぶ分にはこれでいいや。