Remembering Custom Page Settings


Revision as of 23:05, 18 December 2013 by Uecasm (Talk | contribs)
Jump to: navigation, search


If you have added custom pages to your setup, you may also want to add in the ability to remember the values of these settings for later execution of the installer.

One scenario for this is when the user runs the installer a second time, typically to install an upgraded version of your application. You don't want to force your user to type their custom values in again (or potentially worse, mistype or otherwise get them mixed up).

Another scenario is to enable silent installs, where an IT department in a large organisation want to deploy your application onto multiple PCs, using the same settings each time (which may have been customised).

Note that some types of custom settings should only be saved in one or neither of these scenarios; you will need to decide on a case-by-case basis.

Implementing Scenario 1: Subsequent Installs

Inno supports this via its "previous data" mechanism. It will automatically save the previous user selections for the standard wizard pages, and provides a mechanism to add your own custom settings.

To read the previous values: In InitializeWizard (or wherever else you are populating your custom page with data), you should call GetPreviousData with an appropriate unique (to your installer) name, to retrieve the previously-saved value (or the specified default value, for a first install).

procedure InitializeWizard();
  // ...
  MyCustomPage.Values[0] := GetPreviousData('MyCustomValue1', ExpandConstant('{commonappdata}\MyApp\Data'));
  // ...

To save the values at the end of the install, implement the RegisterPreviousData event procedure and call SetPreviousData from within it:

procedure RegisterPreviousData(PreviousDataKey: Integer);
  SetPreviousData(PreviousDataKey, 'MyCustomValue1', MyCustomPage.Values[0]);

Note that a more complete example of this scenario is given in the CodeDlg.iss example script included with Inno.

Implementing Scenario 2: Silent Installs

Inno provides the /SaveInf and /LoadInf command line options to support this scenario; someone first runs the setup interactively with /SaveInf=c:\path\to\somefilename.inf; this will save the settings selected in the standard wizard pages to the file. Once this is done, later silent installations can use /LoadInf=c:\path\to\somefilename.inf to re-use the same settings (assuming that they have access to the same file).

Unfortunately Inno doesn't provide a built-in mechanism to add your own custom settings to these files, but it's not hard to do. First off, you need to define the following helper functions:

  LoadInfFilename, SaveInfFilename: String;

procedure UpdateInfFilenames();
  LoadInfFilename := ExpandFileName(ExpandConstant('{param:loadinf}'));
  SaveInfFilename := ExpandFileName(ExpandConstant('{param:saveinf}'));

function ShouldLoadInf(): Boolean;
  Result := (LoadInfFilename <> '');

function ShouldSaveInf(): Boolean;
  Result := (SaveInfFilename <> '');

function LoadInfString(Section, Key, Default: String): String;
  Result := GetIniString(Section, Key, Default, LoadInfFilename);

procedure SaveInfString(Section, Key, Value: String);
  SetIniString(Section, Key, Value, SaveInfFilename);

(LoadInfString and SaveInfString are optional; you can use GetIni*/SetIni* directly yourself if you prefer.)

Once this is done, you need to add the code to load and save the various settings. First of all, you need to fetch the filenames from InitializeSetup:

function InitializeSetup(): Boolean;
  // ...
  Result := True;

Again, the actual loading is done in InitializeWizard:

  if ShouldLoadInf() then begin
    MyCustomPage.Values[0] := LoadInfString('MyCustomPage', 'Path', MyCustomPage.Values[0]);
    // ...

(Note that if you're implementing Scenario 1 as well, then this code should appear *after* the Scenario 1 code, so that the .inf file "wins"; this is partly why we're using the current value as the default, if the value isn't present in the .inf file for some reason.)

Saving the data can be done from RegisterPreviousData like in Scenario 1, in most cases. In some rare instances (eg. if you've disabled uninstalls) you may need to put it in CurStepChanged(ssPostInstall) instead.

  if ShouldSaveInf() then begin
    SaveInfString('MyCustomPage', 'Path', MyCustomPage.Values[0]);

The Section name can be anything you like, except for 'Setup' (since that's what the standard pages used); a good recommendation is to use something that represents which page the information came from, although you could use one section for all of your pages (or groups of related pages) if you prefer that. Note that once you have specified a section and key name you should not change these in future versions of your installer if you want to support backwards compatibility, which can be useful in upgrade scenarios (although normally you would use Scenario 1 for this).

Another alternative implementation for this scenario is to use custom command line parameters via Inno's {param:xxx} constants, which you can expand in code using ExpandConstant during InitializeSetup and/or InitializeWizard. This allows the user or another process to pass a custom value without having to create a separate file, which can be useful in some cases. You may wish to implement both of these options. If you do implement both, then note that the explicit parameter should "win" over any value specified in the .inf file, and thus the code to read the parameter should occur after the ShouldLoadInf/LoadInfString block shown above.

Personal tools