SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

japan.internet.com翻訳記事

サービスコンポーネントのさまざまな配置方法

COM+サービスを.NET Frameworkのクラスで利用できるようにする

サービスコンポーネントのさまざまな配置方法(後編)

System.EnterpriseServices.RegistrationHelperクラスを使って配置を自動化する

 これらの手動の配置方法は、サイズが小さいアプリケーションにしか利用できません。例えば、ターゲットサーバーにインストールするために複雑なインストールプログラムを必要とする、エンタープライズアプリケーション内でサービスコンポーネントを使用する場合は、そのサービスコンポーネントの配置を、インストールプログラムの一部として行う必要があります。また、アセンブリをGACにインストールする処理をインストールプログラムの一部として行うことが必要になる場合もあります。このようなインストールを実行するスクリプトやバッチファイルを作成することもできますが、もっと簡単な方法があります。Visual Studio .NET のセットアップ/配置プロジェクトを使用すると、コンポーネント登録用のコードを呼び出す機能や、インストール時またはアンインストール時にその他の必要な処理を実行する機能を備えたセットアッププロジェクトを簡単に作成できます。このためには、インストール時またはアンインストール時に実行するカスタム動作を作成する必要があります。カスタム動作を作成するために必要な作業は、System.Configuration.Install.Installerを継承するクラスをアセンブリ内で作成し、配置プロジェクトにカスタムのインストール動作を追加することだけです。今回の例では、先ほど作成したLibraryAppサービスコンポーネントを使うことにします。

 LibraryAppサービスコンポーネントアセンブリにインストーラクラスを追加するには、次のようにします。

  1. LibraryAppプロジェクトを右クリックします。
  2. [Add / New Item...]を選択し、[Add New Item]ダイアログボックスを表示します。
  3. [Categories]ペインで[Code]を選択します。
  4. [Templates]ペインで[Installer Class]を選択し、クラスの名前としてCustomActionInstallerを指定します。

 クラスを作成できたら、そのクラスにInstallメソッドとUninstallメソッドを追加します。

public override void Install(
    System.Collections.IDictionary stateSaver)
{
    try
    {
        string appID = null;
        string typeLib = null;
        // Get the location of the current assembly
        string assembly = GetType().Assembly.Location;
        // Install the application
        RegistrationHelper regHelper = new RegistrationHelper ();
        regHelper.InstallAssembly (assembly, ref appID, ref typeLib,
        InstallationFlags.FindOrCreateTargetApplication);
        // Save the state - you will need this for the uninstall
        stateSaver.Add ("AppID", appID);
        stateSaver.Add ("Assembly", assembly);
    }
    catch(Exception ex)
    {
#if DEBUG
        Debug.WriteLine (ex);
#endif
        StreamWriter writer = File.AppendText ("InstallError.log");
        writer.WriteLine ("Uninstall Error: {0}", ex.Message);
        // If the installer catches the exception it will display
        // an error message.  Show a friendly error message
        throw new ApplicationException
        (
            "Error installing the middle tier", ex);
    }
}


public override void Uninstall(
    System.Collections.IDictionary savedState)
{
    try
    {
        // Get the state created when the app was installed
        string appID = (string)savedState["AppID"];
        string assembly = (string)savedState["Assembly"];
        // Uninstall the application
        RegistrationHelper regHelper = new RegistrationHelper ();
        regHelper.UninstallAssembly (assembly, appID);
    }
    catch ( Exception ex)
    {
        // Don't allow unhandled exceptions during uninstall
#if DEBUG
        Debug.WriteLine (ex);
#endif
        StreamWriter sw = File.AppendText ("InstallError.log");
        sw.WriteLine ("Uninstall Error: {0}", ex.Message);
    }
}

 このコード行について詳しく説明しましょう。まず、現在使用しているアセンブリの場所の参照を取得します。

string assembly = GetType().Assembly.Location;

 ここで、RegistrationHelperクラスのインスタンスを作成します。

RegistrationHelper regHelper = new RegistrationHelper ();

 その後、InstallAssemblyメソッドを呼び出してアセンブリをインストールし、appID変数とtypeLib変数をbyref引数として渡します。アセンブリをインストールしたら、新たに作成したアプリケーションのIDの参照と、ローカル変数に代入されているタイプライブラリを取得します。

regHelper.InstallAssembly (assembly, ref appID, ref typeLib,
InstallationFlags.FindOrCreateTargetApplication);

 次に、用意されているコレクションオブジェクトにAppIDとアセンブリの場所を保存し、後で取得できるようにしておきます。永続化した情報はアプリケーションのアンインストールフェーズで使います。

    stateSaver.Add ("AppID", appID);
    stateSaver.Add ("Assembly", assembly);
}

 このコード行の実行時に例外が発生した場合は、その例外をキャッチし、例外情報をログファイル「InstallError.log」に書き込みます。

    catch(Exception ex)
    {
#if DEBUG
        Debug.WriteLine (ex);
#endif
        StreamWriter writer = File.AppendText ("InstallError.log");
        writer.WriteLine ("Uninstall Error: {0}", ex.Message);
        // If the installer catches the exception it will display
        // an error message.  Show a friendly error message
        throw new ApplicationException
        (
            "Error installing the middle tier", ex);
        }
    }

 Uninstallメソッドでは、まずコレクションオブジェクトからAppIDとアセンブリ情報を取得します。

// Get the state created when the app was installed
string appID = (string)savedState["AppID"];
string assembly = (string)savedState["Assembly"];

 次に、RegistrationHelperクラスのUninstallAssemblyメソッドを呼び出してアセンブリをアンインストールします。

    RegistrationHelper regHelper = new RegistrationHelper ();
    regHelper.UninstallAssembly (assembly, appID);
}

 ここで再び、例外ブロックで、例外情報を外部のログファイル「InstallError.log」に書き込みます。

    catch ( Exception ex)
    {
        // Don't allow unhandled exceptions during uninstall
#if DEBUG
        Debug.WriteLine (ex);
#endif
        StreamWriter sw = File.AppendText ("InstallError.log");
        sw.WriteLine ("Uninstall Error: {0}", ex.Message);
        }
    }

 インストーラクラスを作成できたら、CustomInstallerクラスのInstallメソッドとUninstallメソッドが自動的に呼び出されるように、配置プロジェクトにカスタム動作を追加します。その前に、既存のLibraryAppソリューションに新しい配置プロジェクトを追加する必要があります。このため、次のように「LibraryAppSetup」という新しいプロジェクトを作成します。

 次に、配置プロジェクトにLibraryAppプロジェクトの出力を追加する必要があります。このためには、LibraryAppSetupプロジェクトを右クリックし、[Add]をポイントして[Project Output]を選択します。[Add Project Output Group]ダイアログボックスの[project]ドロップダウンボックスから[LibraryApp]を選択し、出力リストから[Primary Output]を選択します。次に、インストーラがCustomActionInstallerクラスのInstallメソッドとUninstallメソッドを呼び出すように、配置プロジェクトにカスタム動作を追加する必要があります。

カスタム動作を追加する

 カスタム動作はインストールのさまざまなフェーズで呼び出すことができます。インストールが終了した後またはロールバックされた後は、コミットフェーズとロールバックフェーズが発生します。コミットフェーズとロールバックフェーズの際に重要な作業を実行してはなりません。Installメソッドはインストールフェーズで呼び出し、Uninstallメソッドはアンインストールフェーズで呼び出します。

 カスタム動作を追加するには、次のようにします。

  1. LibraryAppSetupプロジェクトを右クリックし、[View]をポイントして[File System]を選択します。
  2. [Install]フェーズを右クリックし、[Add Custom Action...]を選択します。
  3. ターゲットコンピュータのファイルシステムをナビゲートし、カスタム動作クラスが入っているLibraryAppアセンブリを探します。

GACにアセンブリを配置する

 インストールの一部として、GACにサービスコンポーネントを配置することもできます。これは、COM+サーバーアプリケーションにサービスコンポーネントを配置する場合に非常に便利です。GACにサービスコンポーネントをインストールするには、次の操作を実行します。

  1. LibraryAppSetupプロジェクトを右クリックし、[View]をポイントして[File System]を選択します。
  2. 既定では、フォルダのリストにグローバルアセンブリキャッシュフォルダは表示されません。リストにグローバルアセンブリキャッシュフォルダを追加するには、[File System on Target Machin]を右クリックし、[Add Special Folder]をポイントして[Global Assembly Folder]を選択します。
  3. グローバルアセンブリフォルダを右クリックし、[Add]をポイントして[Assembly]を選択し、GACフォルダにアセンブリを追加します。

 これで、インストーラを作成して「LibraryAppSetup.msi」ファイルを実行すると、アセンブリがコンポーネントサービスに登録されているだけでなく、GACにも配置されていることが分かります。

XCOPY配置とサービスコンポーネント

 .NET Frameworkの目標の1つは、XCOPY配置をサポートすることによってシステムのインストールを簡略化することです。XCOPYとは、ファイルやディレクトリを別の場所にコピーするためのMS-DOSコマンドラインユーティリティのことです。XCOPY配置の目的は、コードを実行することなくアプリケーションをリモートサーバーにインストールできるようにすることです。XCOPY配置をサポートするために、CLR/COM+の統合アーキテクチャでは、インストール時に「regsvcs.exe」の実行を無視し、サービスコンポーネントが初めて使用されるときに自動登録を行うような仕組みが用意されています。これを「レイジー登録」と言います。レイジー登録は、ライブラリアプリケーションにサービスコンポーネントを配置する場合に役立ちます。ただし、XCOPY配置にも注意しなければならない欠点があります。

  • COM+システムアプリケーションで定義されている管理者ロールに含まれるユーザーしかCOM+カタログを更新できません。既定の管理者ロールにはローカルの管理者しか含まれていません。そのため、サービスコンポーネントを正しく登録するには、最初にサービスコンポーネントを使うコードに管理者特権を付与する必要があります。そうしないと、登録は失敗します。
  • GACにサービスコンポーネントを配置する場合は適切なディレクトリにファイルをコピーすれば簡単に配置できますが、サーバーアプリケーションにもアセンブリを配置する場合には別の作業が必要になります。特に、メタデータでは自動的に設定されない、COM+サーバーアプリケーションのセキュリティプリンシパルの設定が必要になります。COM+ライブラリアプリケーションに設定済みクラスを配置する場合は、アセンブリがクライアントのプライベートディレクトリに配置されている限り問題ありません。

GACにサービスコンポーネントをインストールすることが必要な場合

 次の条件に当てはまる場合は、GACにサービスコンポーネントをインストールすることが必要です。

  • アプリケーションがSOAP(クライアントとサーバーの両方)または.NET Remotingを使っている場合。
  • マネージドコードからサービスコンポーネントにアクセスし、かつアセンブリの格納ディレクトリが実行可能ファイルとは異なる場合。つまり、マネージドコードからアセンブリを探す場合、アセンブリは、アプリケーションディレクトリ内にないときはGAC内になければなりません。
  • 同じコンピュータ上のすべてのクライアントアプリケーションが同じアセンブリを共有する場合。
  • サービスコンポーネントがCOM+サーバーアプリケーションに配置されている場合。COM+ライブラリアプリケーションに配置されているサービスコンポーネントは、ディレクトリが別々でない限り、GACに置く必要はありません。現在ログオンしているユーザーは管理者グループに含まれていなければなりません。

まとめ

 この記事では、.NET Frameworkに用意されているさまざまなクラスやツールを使ってサービスコンポーネントを配置する方法を説明しました。また、Windowsインストーラテクノロジを利用すると、サービスコンポーネントの配置を自動化するWindowsインストーラプロジェクトを簡単に作成できることも説明しました。

 最後に、この記事を読んでくださった方に感謝します。また、この記事があなたにとって有益であることを願っています。

この記事は参考になりましたか?

連載通知を行うには会員登録(無料)が必要です。
既に会員の方はを行ってください。
japan.internet.com翻訳記事連載記事一覧

もっと読む

この記事の著者

japan.internet.com(ジャパンインターネットコム)

japan.internet.com は、1999年9月にオープンした、日本初のネットビジネス専門ニュースサイト。月間2億以上のページビューを誇る米国 Jupitermedia Corporation (Nasdaq: JUPM) のニュースサイト internet.comEarthWeb.com からの最新記事を日本語に翻訳して掲載するとともに、日本独自のネットビジネス関連記事やレポートを配信。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

Thiru Thangarathinam(Thiru Thangarathinam)

オブジェクト指向アプリケーション開発方法論を用いたアプリケーションのアーキテクチャ設計、設計、開発、および実装に関して約6年の経験を持つ。ソフトウェアライフサイクル(設計、開発およびテスト)にも精通。ASP.NET、.NET Framework、Visual C#.NET、Visual Basic.NET、ADO.NET、XML Webサービス、および.NET Remotingのエキスパートであり、MCAD...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/364 2006/08/22 15:45

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー