LoginSignup
3
1

More than 1 year has passed since last update.

インストーラのカスタム動作のクセ

Last updated at Posted at 2022-05-02

概要

Windowsのインストーラ作成にVisual Studioの拡張機能Microsoft Visual Studio Installer Projects(以降、Installer Projectsと呼ぶ)を使用している方も多いだろう。
インストール後にInstaller Projectsの標準機能では実行できない複雑な処理をする場合はカスタム動作を別途定義してイベント発生時に呼び出す場合がある。
カスタム動作について調べている中でいくつかクセを発見したのでメモしておく。

テスト用セットアッププロジェクト

Installer Projectsのセットアッププロジェクト(TestSetup)からカスタム動作用DLL(CustomAction1CustomAction2)を呼び出している。
カスタム動作の基本的な説明はこの神記事を見ればたちどころにわかる。
カスタム動作の実行順序はこの神記事が非常に詳しい。

CustomAction1.cs
using System.Windows.Forms;
using System.ComponentModel;
using System.Collections;

namespace CustomAction1
{
    [RunInstaller(true)]
    public class CustomAction1 : System.Configuration.Install.Installer
    {
        public override void Install(IDictionary stateSaver)
        {
            base.Install(stateSaver);
            MessageBox.Show(GetType().Name + ": Install");
        }

        public override void Commit(IDictionary savedState)
        {
            base.Commit(savedState);
            MessageBox.Show(GetType().Name + ": Commit");
        }

        public override void Rollback(IDictionary savedState)
        {
            base.Rollback(savedState);
            MessageBox.Show(GetType().Name + ": Rollback");
        }

        public override void Uninstall(IDictionary savedState)
        {
            base.Uninstall(savedState);
            MessageBox.Show(GetType().Name + ": Uninstall");
        }
    }
}
CustomAction2.cs
using System.Windows.Forms;
using System.ComponentModel;
using System.Collections;

namespace CustomAction2
{
    [RunInstaller(true)]
    public class CustomAction2 : System.Configuration.Install.Installer
    {
        public override void Install(IDictionary stateSaver)
        {
            base.Install(stateSaver);
            MessageBox.Show(GetType().Name + ": Install");
        }

        public override void Commit(IDictionary savedState)
        {
            base.Commit(savedState);
            MessageBox.Show(GetType().Name + ": Commit");
        }

        public override void Rollback(IDictionary savedState)
        {
            base.Rollback(savedState);
            MessageBox.Show(GetType().Name + ": Rollback");
        }

        public override void Uninstall(IDictionary savedState)
        {
            base.Uninstall(savedState);
            MessageBox.Show(GetType().Name + ": Uninstall");
        }
    }
}

セットアッププロジェクトのカスタム動作
キャプチャ.PNG

RemovePreviousVersions=TrueのときはUninstallのカスタム動作が呼ばれない?

セットアッププロジェクトのRemovePreviousVersionsTrueにすると新しいバージョンのソフトをインストールする際(バージョンアップ時)に古いバージョンのソフトを自動的にアンインストールしてくれる。
これをしないと複数の異なるバージョンが1つのPC内に同居する状態になってしまう場合があり、不都合が生じる可能性がある。
ここで注意すべきなのは古いバージョンのアンインストール時にカスタム動作のUninstall実行されないことである。

RemovePreviousVersions=Trueでバージョンアップするなら、古いバージョンを削除したときにして、
Uninstallのカスタム動作が呼ばれるかも?と思ったが、
実際は新しいバージョンのInstallCommitのカスタム動作が実行されるだけである。
まあ現状の仕様のほうが多くの人にメリットがあるように思う。

インストール開始前に実行できるカスタム動作はない?

実はカスタム動作として使用できるのはInstallCommitRollbackUninstallだけではなく、この記事で紹介されているOnBeforeInstallOnAfterInstallなどもある。

その中でもOnBeforeInstallはインストール先の環境のチェックやインストール可否の制御に使用できそうな気がするが、
OnBeforeInstallの実行タイミングはファイルの配置がすべて完了した後であって、インストールのプロセスがかなり進んだ後なのだ。
さらに困ったことにインストールを否認した場合のエラーメッセージが非常に不親切なのである。

たとえばCustomAction1.csに以下のコードを追加して人為的に例外を返してやる。
これによってインストールが途中で中断されるはずだ。

protected override void OnBeforeInstall(IDictionary savedState)
{
    base.OnBeforeInstall(savedState);
    MessageBox.Show(GetType().Name + ": OnBefore");
    throw new System.Configuration.Install.InstallException("Errorだあああああ");
}

インストールが開始されてファイルが配置される
スクリーンショット 2022-05-02 163116.png

ここでOnBeforeInstallが実行されて例外発生を示すメッセージが表示されるが、なんだか不親切な嫌な感じ。
d.PNG

OKを押しても立て続けに怪しいエラーが表示される。
3241.PNG

最後はこれ。今回カスタム動作用のDLLを2つ使っているため表示されるものと思われる。
aaa.PNG

もっとこう…あるだろう!!という感じだ。
インストーラの「起動条件」でもインストーラ実行可否の制御はできると思うが、凝ったことをやるのには不向きである。
いいやり方があれば誰か教えてください。

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1