2015/05/31

Inno Setup : 上書きインストールかどうかを確認する

インストーラーを作成するのに、いろいろ便利なので最近は
Inno Setup
http://www.jrsoftware.org/isinfo.php
というのを使っているのだけど、
ちょいとその小ネタを。

Inno Setupには、前回インストールしたものに対して
バージョンアップしたものを上書きインストールしたい場合に、
前回インストールしたときのフォルダを検出して
自動的にそこにインストールしたりしてくれるような
機能が用意されていたりはするのだけど、
「旧バージョンがインストールされてるけどアップデートする?」
的なメッセージを表示させるような機能は用意されていないので、
それを作ってみた。


・・・作ってみたのだが、
これがまた簡単そうで意外と面倒くさかった。
[Code] セクションで自前でスクリプトを書かなければならず、
全く書いたことのなかったよくわかんらんPascal言語の文法で
悩まされることに・・・。

未だに If - else 構文の理屈がよくわんねー


ま、それは置いといて、
こんな感じのスクリプトになった。

[Code]

// ------------------------------------------------------------
// 前回インストールしたアプリケーションの情報が格納されている(はず)の
// レジストリのパスを返す関数。
// Inno Setupで作成したインストーラーは、
// ここにアプリケーション名やらバージョンなどの情報を格納している。
// (試しに regedit で覗いてみるのがおすすめ。)
// ------------------------------------------------------------
function GetAppInstallRegKey() : string;
begin
  Result := 'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\([Setup]セクションのAppIdに設定した値)';
  
end;


// ------------------------------------------------------------
// 上書きインストールかどうかを調べる関数。
// (レジストリに別なバージョンのインストール情報があるかどうかを調べる。)
// ------------------------------------------------------------
function IsUpdateInstall() : Boolean;
var
  key : string;
begin
  key := GetAppInstallRegKey();

  if RegKeyExists(HKEY_LOCAL_MACHINE, key) then begin
    Result := true
  end else begin
    Result := false;
  end;

end;


// ------------------------------------------------------------
// すでにインストールされているヤツのバージョンを取得する関数。
// ------------------------------------------------------------
function GetPrevVersion() : string;
var
  prevVersion : string;
  key : string;
begin
  key := GetAppInstallRegKey();
  if RegQueryStringValue(HKEY_LOCAL_MACHINE, key, 'DisplayVersion', prevVersion) then
  begin
    Result := prevVersion;
  end;

end;


// ------------------------------------------------------------
// インストール開始時に呼び出される関数。
// ------------------------------------------------------------
function InitializeSetup(): Boolean;
var

  // すでにインストールされているヤツのバージョン
  prevVersion : string;

  // 上書きインストールを実行するかどうか
  doUpdate : Boolean;

begin

  // 別なバージョンがインストール済みかどうかを確認して、
  if IsUpdateInstall() then begin

    // そうなら、前回インストールしたヤツのバージョンを取得して、
    prevVersion := GetPrevVersion();

    // メッセージを表示。( #13 で改行文字が入るらしい。)
    // Yes が選択されたら 変数 doUpdate に true が入る。
    doUpdate := MsgBox('バージョン ' + prevVersion + ' がすでにインストールされています。' #13 'バージョン (ほげほげ) で上書きインストールを実行しますか?', mbConfirmation, MB_YESNO) = idYes;
    
    if doUpdate then begin
 
      // Yes が選択されたら、この関数の戻り値に true を設定。
      Result := true;

    end else begin

      // No なら、キャンセルされる旨のメッセージを表示して、
      MsgBox('セットアップはキャンセルされました。', mbInformation, MB_OK);

      // 戻り値に false を設定。
      // この関数が false を返すと、セットアップが中止される。
      Result := false;
      
    end;
    
  end else begin

    // 新規のインストールなので特に何もしない。
    Result := true;
    
  end;

end;


あと、[Setup]セクションで、

DisableDirPage=auto
DisableProgramGroupPage=auto

と書いておく。

DisableDirPage は、
インストール先ディレクトリの選択画面を表示するかどうかのオプション。

DisableProgramGroupPage は、
スタートメニューに作成するプログラムグループを指定する画面を
表示するかどうかのオプション。

これらを、"auto" にしておくと、
新規インストールの時はその画面が表示され、
アップデートするときは表示されずに前回インストール時の
ディレクトリなりプログラムクループなりが自動で選択されるようになる。