CitizenInsane
CitizenInsane

Reputation: 4855

Inno Setup - Automatically generate options to allow user to choose what files to install

I'm using Inno Setup tool to install some program and its associated macros this way:

[Files]
Source: "..\macros\*.js"; DestDir: "{app}\macros"; Flags: ignoreversion

Now what I would like to do is to let the user choose for a subset of macros instead of installing them all. For instance I'd like to show a custom checklistbox page during installation where the user can select for the macros he'd like to install (with extra 'select all', 'select none' shortcut buttons would be great).

Do you know any similar case/example Inno Setup-script I can inspire from ?

NB1: I have no idea of how many macros there is in the ..\macros\ folder, neither the name of them all, so I can't list them all one-by-one in the [Files] section.

NB2: I have read this thread but this not what I'd really like (would need to update the .iss on any change in the macros folder which is not a smart solution) : How can I add a CheckBox for optional files during install? (innosetup)

Upvotes: 2

Views: 948

Answers (2)

Miral
Miral

Reputation: 13030

If you want to define some "groups" of macros in advance (rather than having them be individually selectable), then you can simply arrange your source files into those groups, and then set up components accordingly:

[Components]
Name: macroX; Description: "Macros for X"
Name: macroY; Description: "Macros for Y"

[Files]
Source: "..\macros\macroX\*.js"; DestDir: "{app}\macros"; Components: macroX; Flags: ignoreversion
Source: "..\macros\macroY\*.js"; DestDir: "{app}\macros"; Components: macroY; Flags: ignoreversion

It would be possible to make individual selection within these groups as well, but you'd have to name the files individually:

[Components]
Name: macroX\macro1; Description: "Macro1"
[Files]
Source: "..\macros\macroX\macro1.js"; DestDir: "{app}\macros"; Components: macroX\macro1; Flags: ignoreversion

It's possible to use ISPP to generate code like the above using wildcards, but that is left as an exercise for the reader.


Finally, you can use [Types] to provide select-all / select-none functionality:

[Setup]
AlwaysShowComponentsList=yes
[Types]
Name: all; Description: "All macros"
Name: none; Description: "No macros"
Name: custom; Description: "Custom selection"; Flags: iscustom

And then put Types: all on all of your [Components] entries.

Upvotes: 1

CitizenInsane
CitizenInsane

Reputation: 4855

Solution using preprocessor directives and code emission as proposed by @MartinPrikryl in question comments and described in details in this other thread is a very nice one and I would definitely recommend it.

Here is anyhow some alternative using Pascal scripting only:

  1. First I let the Setup installing all the macros, but I watch for them using a AfterInstall handler in the [File] section:

    [Files]
    Source: ".\macros\*.txt"; DestDir: "{app}\macros"; Flags: ignoreversion; AfterInstall: AfterInstallEachMacro;
    
  2. Handling procedure AfterInstallEachMacro just records all macros in global variables of the [Code] section and populates some extra wizard page that will be displayed after installation is completed:

    procedure AfterInstallEachMacro();
    var 
      filename : String; 
    begin
    
      filename := CurrentFileName;
      filename := ExpandConstant(filename);
      GMacrosFullFilenames.Add(filename);
    
      filename := ExtractFileName(filename);  
      GMacrosSelectectionPage.Add(filename);
      GMacrosSelectectionPage.Values[GMacrosTotalCount] := True;
      GMacrosTotalCount := GMacrosTotalCount + 1;
    
    end;
    
  3. Finally, once leaving that last wizard page, I simply delete macros the user did not selected:

    function NextButtonClick(CurPageID: Integer): Boolean;
      var index: Integer;
    begin
      Result := true; 
    
      {* When leaving page for macro selection *}
      if (CurPageID = GMacrosSelectectionPage.ID) then begin
    
        {* Delete macros the user do not want *}
        for index := 0 to (GMacrosTotalCount - 1) do 
        begin
          if (not(GMacrosSelectectionPage.Values[index])) then begin
            DeleteFile(GMacrosFullFilenames[index]);
          end;
        end;
    
      end;
    end;
    

This approach is maybe less elegant or can be further improved but was better suited for my particular case than solution proposed by @MartinPrikryl.

Full innoscript is hosted here. Here is how it looks like:

Choosing macros to install

Upvotes: 2

Related Questions