注意この記事の最新版は「カスタム動作エディタの使い方」で公開しています。Installerパッケージで使用するカスタムアクションを指定することができます。Installerだけの機能では実現が難しい動作をEXE、DLL、スクリプト等を使って行うものです。カスタムアクションがどのようなものか、簡単な例を見てみましょう。ここでは、VBScriptを使用することにします。はじめにカスタムアクションで使用するスクリプトを作成します。ここでは次のようなごく簡単なスクリプトを作成し、"action.vbs"という名前で保存します。メッセージボックスを表示し、「こんにちは」と表示するだけのスクリプトです。"こんにちは"まずは、この"action.vbs"をデプロイメントプロジェクトに追加します。ソリューションエクスプローラでプロジェクトを右クリックし、メニューの[追加]-[ファイル]で追加できます。次に「カスタム動作エディタ」を開き、スクリプトを追加します。カスタム動作を開くには、ソリューションエクスプローラでプロジェクトを右クリックし、メニューの[表示]-[カスタム動作]を選択します。カスタム動作エディタには4つのノードがありますが、これらの説明は後に回し、ここでは「インストール」ノードにカスタムアクションを追加します。「インストール」ノードを右クリックし、メニューの[カスタム動作の追加]で表示される「プロジェクトから項目を選択」ダイアログで"action.vbs"を選択し、OKをクリックします。これでカスタムアクションが追加されました。ビルドして試してみましょう。作成したMSIファイルを実行すると、「(アプリケーション名)をインストールしています」というステップの途中で「こんにちは」というメッセージボックスが表示されるはずです。上記の例では、スクリプトファイルがアプリケーションフォルダに配置されます。スクリプトファイルを配置しないようにするには、ソリューションエクスプローラで"action.vbs"を選択し、ExcludeプロパティをTrueにします。ExcludeプロパティがFalseの場合、MSIファイルのCustomActionテーブルに登録されるカスタムアクションのTypeは22となります。Typeは6となります。†カスタム動作エディタには4つのノード「インストール」、「確定」、「ロールバック」、「アンインストール」があります。それぞれが何を意味しているかについては、ヘルプの「カスタム動作エディタ」で説明されています。カスタム動作エディタこの説明を以下に引用させていただきます。このノードの下のカスタム動作は、インストールの確定フェーズの最後に実行されます。フェーズが問題なく終了すると発生します。フェーズの最後に実行されます。フェーズは、インストール中にエラーが発生すると発生します。フェーズの最後に実行されます。フェーズは、アプリケーションがアンインストールされると発生します。詳しく調べるには、MSIファイルの中身をOrcaで覗いてみる必要があるでしょう。いう訳で、実際に調べてみました。「インストール」、「確定」、「ロールバック」に追加されたカスタムアクションは、すべてInstallExecuteSequenceテーブルにConditionが「$(スクリプトファイルのコンポーネントのID)>2」(注)、Sequenceが5999(複数登録すると、5998、5997...となる)として登録されます。「$(スクリプトファイルのコンポーネントのID)>2」の"2"は"msiInstallStateAbsent"を表しており、2より大きいということは、このコンポーネントがインストールされたということを示しています。Sequenceが5999というのは、StartServicesの後、RegisterUserの前ということになります。InstallExecuteSequence」をご覧ください。REMOVE~="ALL"」となります。完全に削除する以外のときということになります。詳しくは、次のページをご覧ください。Property「アンインストール」に追加されたカスタムアクションは、InstallExecuteSequenceテーブルにConditionが「$(スクリプトファイルのコンポーネントのID)=2」(注)、Sequenceが1699(複数登録すると、5998、5997...となる)として登録されます。Sequenceが1699というのは、MsiUnpublishAssembliesの後、UnpublishComponentsの前ということになります。「インストール」、「確定」、「ロールバック」の違いは、CustomActionテーブルのTypeに表れます。「インストール」、「確定」、「ロールバック」のTypeはそれぞれ、1046、1558、1302となります。Options」を調べれば分かります。Actions」ということになります。詳しくは、下記のリンク先をご覧ください。上記で紹介したようなスクリプト以外に、EXEやDLLファイルをカスタムアクションに使用することもできます。EXEはマネージコードでも構いませんが(注)、DLLはアンマネージコードである必要があります。Installクラスを使用したカスタムアクションの場合は、DLLでも大丈夫です。ここからは、Installクラスを使った方法を紹介します。注.EXEファイルをそのまま実行する場合は、InstallerClassプロパティをFalseにする必要があります。Frameworkには、「Installerクラス」というクラスが用意されており、これをカスタムアクションに使用することができます。Installerクラスはじめに、簡単な例から紹介します。新しいクラスライブラリのプロジェクトを作成します。ここではデプロイメントプロジェクトと同じソリューション内に作成し、名前を「CustomAction」としました。このクラスの参照設定に、「System.Configuration.Install.dll」を追加します(ここではMessageBoxを使用しているため、「System.Windows.Forms.dll」も追加します)。次に、Installerクラスの派生クラスを作成し、RunInstallerAttribute属性を追加し、Trueにします。必要に応じてInstall、Commit、Rollback、Uninstallメソッドをオーバーライドします。これらのメソッドは、それぞれ「インストール」、「確定」、「ロールバック」、「アンインストール」の時に呼び出されます。これらのメソッドでは、まずはじめに基本クラスのメソッドを呼び出します。コンポーネントの既定のメソッドのオーバーライドここでは以下のようなコードでビルドし、DLLファイル「CustomAction.dll」を作成しました。}このカスタムアクションをデプロイメントプロジェクトで使用するためには、先ほどと同じように、作成したDLLをデプロイメントプロジェクトに追加してから(ここでは、「プロジェクト出力」から、「CustomActionプロジェクトのプライマリ出力」を追加しました)、カスタム動作エディタに追加します。ここでは、4つのノードすべてに追加するために、「カスタム動作」のノードを右クリックし、メニューの[カスタム動作の追加]を選び、「CustomActionのプライマリ出力」を選択します。Installerクラスをカスタムアクションとして使用するには、カスタム動作のInstallerClassプロパティをTrueとする必要がありますが、デフォルトでTrueのため、このままでOKです。ビルドしてMSIファイルを作成し、実行してみましょう。VBScriptの例と同じように、インストールの最後の方で「Install」と表示され、その後「Commit」と表示されます。アンインストール時には、「Uninstall」と表示されます。補足.ここではInstall、Commit、Rollback、Uninstallメソッドをすべてオーバーライドしましたが、必要なものだけで大丈夫です。補足.ここでは、Installerクラスを独自に作成しましたが、VS.NETでは、「コンポーネントの追加」で追加することができます。具体的には、VS.NETのソリューションエディタでInstallerクラスを追加したいプロジェクトを右クリックし、メニューの[追加]-[コンポーネントの追加]から「新しい項目の追加」ダイアログを表示し、「インストーラクラス」を選択します。補足.ここではカスタムアクションのためだけのDLLを作成しましたが、配布するアプリケーションにInstallerクラスの派生クラスを追加する方法もあり、MSDN等では、主にこの方法が紹介されています。補足.この方法では、先ほどのVBScriptの例と違い、ExcludeプロパティをTrueにしてDLLファイルをMSIファイルに埋め込むことはできません。例によってOrcaにより、作成されたMSIファイルの詳細を見てみます。Installerクラスを使った場合、カスタム動作を一つ追加すると、CustomActionテーブルに2つの列が追加されます。「インストール」ノードに追加されたカスタム動作の場合、例えば、次のような2つの列が追加されます。"[VSDFxConfigFile]"Action:_B2459EE5_658C_4EF0_BCE3_810CFFFBC274.uninstallType:1025Source:InstallUtilTarget:ManagedInstallまず、Type51のカスタムアクションにより、プロパティが設定されます。51次に、Type1025のカスタムアクションにより、InstallUtilのManagedInstall関数が呼び出され、この時に先に設定されたプロパティが引数として渡されます。Type1025は、Type1+msidbCustomActionTypeInScriptですので、埋め込まれたDLLを呼び出すカスタムアクションであることが分かりますが、実際にInstallUtilはBinaryテーブルに埋め込まれています。InstallUtilという名前からInstallUtil.exeが埋め込まれていると思われるかもしれませんが、ここに埋め込まれているのはInstallUtilLib.dllです。"[#_A367697580D6A572E31AB7AA55DFF20A]"」の「_A367697580D6A572E31AB7AA55DFF20A」は、Installerクラスのあるファイル(ここでは、CustomAction.dll)のIDであり、先頭に「#」が付いていることから、ファイルのパスを意味していることになります。これらのカスタムアクションは、InstallExecuteSequenceテーブルで使用されます。Type51のカスタムアクションの後で、Type1のカスタムアクションが実行されます。「インストーラ」ノード以外に追加されたカスタム動作でも同様の列がCustomActionテーブルに追加されます。「install」の文字列がすべて「commit」「rollback」「uninstall」に置き換わります。TypeはVBScriptの例で紹介したのと同じオプションフラッグが付きます。†カスタム動作にデータ(文字列)を渡すには、CustomActionDataプロパティを使います。Installerクラスを使ったときの方法から説明します。Installerクラスを使ったカスタムアクションにデータを渡すときは、CustomActionDataプロパティに「/name=value」という形式で指定します。ここで「name」は名前で、「value」はその値を示します。複数のデータを渡す場合は、スペース文字で区切ります。/name2=value2」のようにします。1"のように"で囲みます。"で囲まれた文字列の最後が\となるときは、さらに\を付けて、"\\"とします。Installerのプロパティを使うときは、[]で囲みます。Installerクラス内でデータを取得するには、InstallContext.Parametersプロパティを使います。/dir="[TARGETDIR]\"と入力します。Installerのプロパティです。[TARGETDIR]が"で囲まれているのは、[TARGETDIR]にスペースが含まれる可能性があるからで、また最後に\が付いているのは、[TARGETDIR]の最後に\が付くからです。このデータを取得するために、InstallerクラスのInstallメソッドを次のようにオーバーライドします。targetdir);}変数valは"value"となり、targetにはインストール先のフォルダのパスが入ります。このようにCustomActionDataプロパティを指定した時、作成されるMSIファイルのCustomActionテーブルは次のようになります。CustomActionDataプロパティで指定された文字列が引数として渡されていることが分かります。"[VSDFxConfigFile]"VBScriptの場合は、CustomActionDataプロパティで指定された文字列をそのままSession.Propertyで取得できます。CustomActionDataプロパティを「[TARGETDIR]」とした場合、次のようなVBScriptにより、インストール先のフォルダのパスを表示できます。val複数のデータを渡すには、独自に区切り文字を決めるしかないようです。†Installerクラスを使ったカスタムアクションでエラーを発生させて、インストールが失敗するようにするには、InstallExceptionオブジェクトをスローします。具体例として、次のようなカスタムアクションを試してみましょう。}}作成されるMSIファイルを実行すると、「テストエラー」というダイアログが表示され、その後、「Rollback」というメッセージボックスが表示されます。ロールバックが行われます。Installerにエラーを報告し、コールバックすることはできませんが、次のようにしてエラーダイアログを表示することはできます。record参考.カスタム動作でのエラー処理カスタム動作に関して、ヘルプにも幾つかの例が載っていますので、参考にしてください。