Inno Setupのスクリプトでファイルを配置する
Inno Setupでファイルやフォルダをインストールする際、[Files]セクションを利用するのが基本です。しかし、いろいろな事情で、スクリプトを使ってファイルをインストールしたいこともあります。こういった場合、インストーラー本体とインストールするファイルをユーザーの環境の一時的な場所に展開しておき、インストーラーで適切な場所にファイルをコピーすることになります。こういった用途には、CreateDir()やCopyFile()などの関数を利用できます。しかし、ファイル数が多いとコーディングも大変ですし、ファイル構成が変わるとせっかく書いたコードを編集することになり大変です。
そこでXCopy()関数
Windowsのコマンドプロンプトでは、フォルダ構造を保ったまま複数のファイルをコピーするXCOPYコマンドがあります。この機能がInno Setupのスクリプトで使えれば便利なのですが、残念ながら用意されていません。そこで、独自に実装してみたのですが、思ったより簡単にできたので紹介します。手順的には、コピー元のフォルダとファイルを列挙して順次コピーしていくだけなので、列挙方法をInno Setupのヘルプで調べます。まずは、FindFirst()とFindNext()を組み合わせて・・・と思いFindFirst()のヘルプを見ると、下記のサンプルのコードが載っています。
var
FilesFound: Integer;
FindRec: TFindRec;
begin
FilesFound := 0;
if FindFirst(ExpandConstant('{sys}\*'), FindRec) then begin
try
repeat
// Don't count directories
if FindRec.Attributes and FILE_ATTRIBUTE_DIRECTORY = 0 then
FilesFound := FilesFound + 1;
until not FindNext(FindRec);
finally
FindClose(FindRec);
end;
end;
MsgBox(IntToStr(FilesFound) + ' files found in the System directory.',
mbInformation, MB_OK);
end;
ん! 再帰を使えば「このコードそのまま使えるじゃん!」ということに気づき、ちょっとの改造でXCopy()関数を実装しました。
//---------------------------------------------------------------------------
// sourcePathフォルダをdestPathフォルダ以下にファオルダ構造を保ってコピーする
//---------------------------------------------------------------------------
procedure XCopyFile(sourcePath, destPath: String);
var
FindRec: TFindRec;
begin
if FindFirst(sourcePath+'\*', FindRec) then begin
try
repeat
if (FindRec.Name<>'.') and (FindRec.Name<>'..') then begin // フォルダ自身と親フォルダは処理しない
if FindRec.Attributes and FILE_ATTRIBUTE_DIRECTORY = 0 then begin
// ファイルのとき
CopyFile(sourcePath + '\' + FindRec.Name, destPath + '\' + FindRec.Name, False);
end else begin
// ディレクトリのとき
CreateDir(destPath + '\' + FindRec.Name);
XCopyFile(sourcePath + '\' + FindRec.Name, destPath + '\' + FindRec.Name);
end;
end;
until not FindNext(FindRec);
finally
FindClose(FindRec);
end;
end;
end;
FindFirst()とFindNext()は、カレントディレクトリ「.」と親ディレクトリ「..」も返すので、これらを処理しないようにする必要がありました。