1
votes

I wrote a setup script to install a third-party setup.exe that I run to install it silently. When I run this external setup.exe, I must specify what products to install through its command-line parameters. For this, I have a dozen of tasks, each representing the products to be installed or not.

Because are too many tasks, I thought in a simpler and smarter way than writing this line below with And/And Not task checks 12*12 times...

[Run]
Filename: {tmp}\Setup.exe; Parameters: /ProductNames=product1,product2,etc...; \
    Flags: shellexec WaitUntilTerminated; StatusMsg: Installing products...; \
    Tasks: product1 and product2 and not product3 etc...

Maybe this is not the best approach to achieve this, but in the [Code] section I declared some variables that stores the product names to install or not, and I would like to be able reference those vars, like this:

[Run]
Filename: {tmp}\Setup.exe; Parameters: /ProductNames={%product1}{%product2}; \
    Flags: shellexec WaitUntilTerminated; StatusMsg: Installing products...;

So that will simplify the [Run] section to just that line, instead of dozens and dozens of variations...

How can I do this?.

If it is not possible, then as an alternative I can declare a function that returns a comma-delimited string with the product names to be installed, but I don't know how to call it in the [Run] section above to use the return value of that function inside the Parameters string of the external setup.exe that I run... I mean, something like this

[Run]
Filename: {tmp}\Setup.exe; Parameters: /ProductNames={MyFunction()}; \
    Flags: shellexec WaitUntilTerminated; StatusMsg: Installing products...;

This is a minified example of my [Code] section:

[Code]

var 
  product1: string;
  product2: string;

procedure TaskOnClickCheck(Sender: TObject); 
begin
  { reset values. }
  product1 := ''
  product2 := ''

  if IsTaskSelected('product1') then 
  begin
    product1 := ',product1 Name'
  end;

  if IsTaskSelected('product2') then 
  begin
    product2 := ',product2 Name'
  end;

end;

procedure InitializeWizard();
begin
  WizardForm.TasksList.OnClickCheck := @TaskOnClickCheck;
end;
1

1 Answers

2
votes

Use a scripted constant:

[Run]
Filename: {tmp}\Setup.exe; Parameters: /ProductNames={code:GetProducts}; \
    Flags: shellexec waituntilterminated; StatusMsg: Installing products...

[Tasks]
Name: product1; Description: "Product 1"
Name: product2; Description: "Product 2"
Name: product3; Description: "Product 3"
[Code]

function GetProducts(Param: string): string;
var
  ProductList: TStringList;
begin
  ProductList := TStringList.Create;

  if IsTaskSelected('product1') then ProductList.Add('Prod1');
  if IsTaskSelected('product2') then ProductList.Add('Prod2');
  if IsTaskSelected('product3') then ProductList.Add('Prod3');

  Result := ProductList.CommaText;
  ProductList.Free;
  Log('Product list is: ' + Result);
end;

ProductList.CommaText above will produce an output like Prod1,Prod2 (though if there are spaces in product names, it will produce "Prod 1","Prod 2").