Our software supports a range (~70) of file associations that a user can select to associate with our application.
It is straight forward to set this up in the Registry
section of the installer and use flags to control behavior during uninstalling as well as the Check
flag to control if it should be written to the registry or not.
The users can control which associations to setup via a custom page with a CheckListBox
.
What I'm wondering now is if there is a method to loop over the CheckBox
items of the CheckListBox
inside the Registry
section? Currently I can only imagine that I would have to create all the registry entries via the Code
section but that would require me to also write the code for the uninstaller as the flags controlling the uninstall behavior are not available here?
You cannot use Pascal code to generate Registry
section entries.
But you can use Inno Setup preprocessor to generate both your Registry
sections as well as the code for adding the extensions to the CheckListBox
. Something like this:
#define Extension(Mode, Ext) \
Mode == "Registry" ? \
"Root: HKCU; Subkey: ""Software\My Company""; ValueType: string; ValueName: """ + \
Ext + """; ValueData: ""yes""; Check: RegisterExtension('" + Ext + "')" + NewLine \
: Mode == "Check" ? \
" if (Ext = '" + Ext + "') and CheckListBox.Checked[I] then Exit;" + NewLine + \
" Inc(I); " + NewLine \
: Mode == "AddCheckbox" ? \
" CheckListBox.AddCheckBox('" + Ext + "', '', 0, True, True, False, True, nil);" + \
NewLine \
: ""
#define Extensions(Mode) \
Extension(Mode, 'jpg') + \
Extension(Mode, 'gif') + \
Extension(Mode, 'png') + \
""
[Registry]
#emit Extensions("Registry")
[Code]
var
CheckListBox: TNewCheckListBox;
function RegisterExtension(Ext: string): Boolean;
var
I: Integer;
begin
I := 0;
Result := True;
#emit Extensions("Check")
Result := False;
end;
procedure AddExtensionsToCheckListBox;
begin
#emit Extensions("AddCheckbox")
end;
Registry
entry is just a (useless) example.AddExtensionsToCheckListBox
somewhere from the code, where you are creating the CheckListBox
.See my other answer for a less elegant, but more readable solution.
To see what this does, add this to the end of your script:
#expr SaveToFile(AddBackslash(SourcePath) + "Preprocessed.iss")
Check the the Preprocessed.iss
after compilation. It should give you something like (empty lines and line wrapping added for readability):
[Registry]
Root: HKCU; Subkey: "Software\My Company"; ValueType: string; ValueName: "jpg"; \
ValueData: "yes"; Check: RegisterExtension('jpg')
Root: HKCU; Subkey: "Software\My Company"; ValueType: string; ValueName: "gif"; \
ValueData: "yes"; Check: RegisterExtension('gif')
Root: HKCU; Subkey: "Software\My Company"; ValueType: string; ValueName: "png"; \
ValueData: "yes"; Check: RegisterExtension('png')
[Code]
var
CheckListBox: TNewCheckListBox;
function RegisterExtension(Ext: string): Boolean;
var
I: Integer;
begin
I := 0;
Result := True;
if (Ext = 'jpg') and CheckListBox.Checked[I] then Exit;
Inc(I);
if (Ext = 'gif') and CheckListBox.Checked[I] then Exit;
Inc(I);
if (Ext = 'png') and CheckListBox.Checked[I] then Exit;
Inc(I);
Result := False;
end;
procedure AddExtensionsToCheckListBox;
begin
CheckListBox.AddCheckBox('jpg', '', 0, True, True, False, True, nil);
CheckListBox.AddCheckBox('gif', '', 0, True, True, False, True, nil);
CheckListBox.AddCheckBox('png', '', 0, True, True, False, True, nil);
end;
For somewhat different approach that makes use of event attributes that were not available, at the time I wrote this answer:
Array Variables and dynamic access in [Code] section