2
votes

I should need your help.

I wonder if there is a possibility in Inno to set 2 different installation masks for 2 products (by selecting from the Dropdown).

We will call the 2 different installations “SETUP” and “PROGRAM”.

When Installing “SETUP” we should have the possibility to check/uncheck boxes for:
A.exe , B.exe, C.exe and D.exe that will be installed (no other check boxes should be seen).

When installing “PROGRAM” we should have the possibility to check/uncheck boxes for A.exe, B.exe (common to “SETUP”), F.exe and G.exe (no other boxes should be seen).

I tried to add the “Flags : fixed” in [Components] section but am unable to hide the checkboxes linked to the other installation (from the drop down menu when selecting to install SETUP or PROGRAM we see the “greyed ”check box).

Is there a way to hide completely “C.exe” and “D.exe” when installing “PROGRAM” and hide completely “F.exe” and “G.exe” when installing “SETUP” ?

Thanks in advance for your help.

Meleena.

1
The only way I can think of is deleting those items from the components list. However, at this time you'll need to iterate from bottom to top deleting those matching the component name. - TLama
Hi and thanks for your answer.Be patient as I am not a programmer may you please show me the correct coding with iteration ? Meleena. - Meleena
I've posted just a (commented) principle of how to delete components at runtime, since you didn't say by what do you determine the installation type. If you were having some trouble implementing it into your real situation, let me know explaining what means "when installing “SETUP”" and when installing “PROGRAM”. - TLama

1 Answers

5
votes

To hide components at runtime, the only way I can think of (in current version) is deleting the items from the components list. At this time, you can reliably identify component only by its description, so the idea in this code is making a list of component descriptions, iterating ComponentsList and deleting all that matches by its description:

[Setup]
AppName=My Program
AppVersion=1.5
DefaultDirName={pf}\My Program

[Components]
Name: "ProgramA"; Description: "{cm:CompDescrProgramA}";
Name: "ProgramB"; Description: "{cm:CompDescrProgramB}";
Name: "ProgramC"; Description: "{cm:CompDescrProgramC}";
Name: "ProgramD"; Description: "{cm:CompDescrProgramD}";

[CustomMessages]
; it's much better for maintenance to store component descriptions
; into the [CustomMessages] section
CompDescrProgramA=Program A
CompDescrProgramB=Program B
CompDescrProgramC=Program C
CompDescrProgramD=Program D

[Code]
function ShouldHideCD: Boolean;
begin
  // here return True, if you want to hide those components, False
  // otherwise; it is the function which identifies the setup type
  Result := True;
end;

procedure DeleteComponents(List: TStrings);
var
  I: Integer;
begin
  // iterate component list from bottom to top
  for I := WizardForm.ComponentsList.Items.Count - 1 downto 0 do
  begin
    // if the currently iterated component is found in the passed
    // string list, delete the component
    if List.IndexOf(WizardForm.ComponentsList.Items[I]) <> -1 then
      WizardForm.ComponentsList.Items.Delete(I);
  end;
end;

procedure InitializeWizard;
var
  List: TStringList;
begin
  // if components should be deleted, then...
  if ShouldHideCD then
  begin
    // create a list of component descriptions
    List := TStringList.Create;
    try
      // add component descriptions
      List.Add(ExpandConstant('{cm:CompDescrProgramC}'));
      List.Add(ExpandConstant('{cm:CompDescrProgramD}'));
      // call the procedure to delete components
      DeleteComponents(List);
    finally
      // and free the list
      List.Free;
    end;
  end;
end;

Note, that once you'll delete the items from the ComponentsList, you cannot add them back because each item is holding a TItemState object instance which is released at deletion and there's no way to create nor define such object from script.