Remembering Custom Page Settings

From ISXKB

(Difference between revisions)
Jump to: navigation, search
(New page: ==Overview== 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 scen...)
(Updated based on JR's notes)
Line 41: Line 41:
   LoadInfFilename, SaveInfFilename: String;
   LoadInfFilename, SaveInfFilename: String;
   
   
-
  function ExpandRelativeToSetup(Path: String): String;
+
  procedure UpdateInfFilenames();
  begin
  begin
-
   if (Path <> <nowiki>''</nowiki>) and (ExtractFileDrive(Path) = <nowiki>''</nowiki>) and (Path[1] <> '\') then begin
+
   LoadInfFilename := ExpandFileName(ExpandConstant('{param:loadinf}'));
-
    Result := ExpandFileName(ExpandConstant('{src}\') + Path);
+
  SaveInfFilename := ExpandFileName(ExpandConstant('{param:saveinf}'));
-
  end else begin
+
-
    Result := Path;
+
-
  end;
+
  end;
  end;
   
   
-
  function ShouldSaveInf(): Boolean;
+
  function ShouldLoadInf(): Boolean;
  begin
  begin
-
  SaveInfFilename := ExpandRelativeToSetup(ExpandConstant('{param:saveinf}'));
+
   Result := (LoadInfFilename <> <nowiki>''</nowiki>);
-
   Result := (SaveInfFilename <> <nowiki>''</nowiki>);
+
  end;
  end;
   
   
-
  function ShouldLoadInf(): Boolean;
+
  function ShouldSaveInf(): Boolean;
  begin
  begin
-
  LoadInfFilename := ExpandRelativeToSetup(ExpandConstant('{param:loadinf}'));
+
   Result := (SaveInfFilename <> <nowiki>''</nowiki>);
-
   Result := (LoadInfFilename <> <nowiki>''</nowiki>);
+
  end;
  end;
   
   
Line 74: Line 69:
(<code>LoadInfString</code> and <code>SaveInfString</code> are optional; you can use <code>GetIni*</code>/<code>SetIni*</code> directly yourself if you prefer.)
(<code>LoadInfString</code> and <code>SaveInfString</code> are optional; you can use <code>GetIni*</code>/<code>SetIni*</code> directly yourself if you prefer.)
-
Once this is done, you need to add the code to load and save the various settings.  Again, loading is done in <code>InitializeWizard</code>:
+
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 <code>InitializeSetup</code>:
 +
function InitializeSetup(): Boolean;
 +
begin
 +
  UpdateInfFilenames();
 +
  // ...
 +
  Result := True;
 +
end;
 +
 
 +
Again, the actual loading is done in <code>InitializeWizard</code>:
   if ShouldLoadInf() then begin
   if ShouldLoadInf() then begin
Line 83: Line 86:
(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.)
(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 <code>RegisterPreviousData</code> like in Scenario 1, in most cases.  In some rare instances you may need to put it in <code>CurStepChanged(ssPostInstall)</code> instead.
+
Saving the data can be done from <code>RegisterPreviousData</code> like in Scenario 1, in most cases.  In some rare instances (eg. if you've disabled uninstalls) you may need to put it in <code>CurStepChanged(ssPostInstall)</code> instead.
   if ShouldSaveInf() then begin
   if ShouldSaveInf() then begin

Revision as of 06:23, 1 April 2011

Overview

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();
begin
  // ...
  MyCustomPage.Values[0] := GetPreviousData('MyCustomValue1', ExpandConstant('{commonappdata}\MyApp\Data'));
  // ...
end;

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);
begin
  SetPreviousData(PreviousDataKey, 'MyCustomValue1', MyCustomPage.Values[0]);
end;

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:

[Code]
var
  LoadInfFilename, SaveInfFilename: String;

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

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

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

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

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

(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;
begin
  UpdateInfFilenames();
  // ...
  Result := True;
end;

Again, the actual loading is done in InitializeWizard:

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

(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]);
    //...
  end;

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 if you prefer that.

Personal tools
Ads: