Inno Setup でもインクルードガードが有効だった

何らかのアプリケーションのインストーラーを作成する際には Inno Setup と言うソフトウェアを利用しているのですが,ここの Pascal スクリプト部分([Code] セクション)を再利用したいと思う事が多々あります.Inno Setup の Pascal スクリプトは(オプションで?)プリプロセッサが使えるので,#inlcude "libraries.iss" みたいに書く事で再利用したい部分をライブラリ化する事もできるのですが,C と同じで多重インクルード問題に悩まされます.

それで,C と同じ問題なら C と同じ解決手段が使えるだろうと言う事で,インクルードガードを書いてみました.以下のコードは,.NetFramework がインストールされているかどうかを判定する関数をライブラリ化したものです.

#ifndef CUBESOFT_WINDOWS_ISS
#define CUBESOFT_WINDOWS_ISS

// ------------------------------------------------------------------------- //
//
//  IsDotNetDetected
//
//  Indicates whether the specified version and service pack of the
//  .NET Framework is installed.
//
//  Version -- required .NET Framework version:
//    'v1.1'          .NET Framework 1.1
//    'v2.0'          .NET Framework 2.0
//    'v3.0'          .NET Framework 3.0
//    'v3.5'          .NET Framework 3.5
//    'v4\Client'     .NET Framework 4.0 Client Profile
//    'v4\Full'       .NET Framework 4.0 Full Installation
//
//  Service -- required service pack level:
//    0               No service packs required
//    1, 2, etc.      Service pack 1, 2, etc. required
// ------------------------------------------------------------------------- //
function IsDotNetDetected(Version: String; Service: Cardinal): Boolean;
var
    key: String;
    install, count: Cardinal;
    success: Boolean;
begin
    if (Version = 'v1.1') then Version := Version + '.4322'
    else if (Version = 'v2.0') then Version := Version + '.50727';
    key := 'SOFTWARE\Microsoft\NET Framework Setup\NDP\' + Version;
    
    // .NET 3.0 uses value InstallSuccess in subkey Setup
    if Pos('v3.0', version) = 1 then success := RegQueryDWordValue(HKLM, key + '\Setup', 'InstallSuccess', install)
    else success := RegQueryDWordValue(HKLM, key, 'Install', install);
    
    // .NET 4.0 uses value Servicing instead of SP
    if Pos('v4', version) = 1 then success := success and RegQueryDWordValue(HKLM, key, 'Servicing', count)
    else success := success and RegQueryDWordValue(HKLM, key, 'SP', count);
    
    Result := success and (install = 1) and (count >= Service);
end;

#endif // CUBESOFT_WINDOWS_ISS

これを適当に何度もインクルードしてみたのですが,確かに多重定義エラーが発生しなくなりました.Inno Setup でもやはりインクルードガードは有効なようです.

後から考えれば,「そりゃプリプロセッサがあるんだから #ifndef とか #if defined(hgoe) くらい用意してあるだろうよ」と思うのですが,知識が十分にない状態で突き進むとそう言った事にまであまり考えが巡らないので,いろいろ注意しないとなと思いました.Inno Setup の Pascal スクリプトは,未だに「クラスってどうやって書くんだろう」とか基本的な部分の理解が足りていないので,どこかで一度真面目に勉強しなければと感じています.