2015年5月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" にしておくと、
新規インストールの時はその画面が表示され、
アップデートするときは表示されずに前回インストール時の
ディレクトリなりプログラムクループなりが自動で選択されるようになる。



2015年4月26日日曜日

こっそり更新中

ずいぶん久しぶりの投稿になってしまったけど、
まぁ、毎度のことなのでそれは置いとくとして。

ImgViewerをこっそり更新してます。
何となく自分で使っていて不便なところをちまちまと。

画像の表示順を
WindowsのStrCmpLogicalW関数を使って
エクスプローラーの表示順に合わせてみたり、
FreeImageで画像のメタデータ(Exif情報とか)を簡単に取得できるので、
それを見れるようにしてみたりとか。

最近はあんまり新しいソフトウェアを作るネタも時間もないのだけど、
たまーに何かコードを書きたくなるんだよね・・・。
や、仕事ではいつもコード書いてるんだけど、
それとは別に、趣味というかお遊び的に好き勝手に
なにか気の向くままに作りたいというか。

そういや、Visual Studio を 2012 Expless に乗り換えたのだけど、
インストーラーが前と同じ方法では作れなくなってしまったので
なにかいいのはないかと探していたのだけど、
「Inno Setup」
というのが便利そう。

インストーラーとして必要な機能はほとんど一通りそろっているし、
スクリプト書けば、かなりいろいろできそうだし。

ただ、使っているユーザーは多そうなのだが、
どうにも日本語の情報が少なくて少々苦労する・・・。

あと、Pascalの文法が謎。
情報少なすぎるし、
if elseの構文が未だにどーいう理屈なのかよくわからん。