40

I am preparing an installer with Inno Setup. But I'd like to add an additional custom (none of the available parameters) command line parameters and would like to get the value of the parameter, like:

setup.exe /do something

Check if /do is given, then get the value of something. Is it possible? How can I do this?

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
Similar
  • 407
  • 1
  • 4
  • 4

10 Answers10

43

With InnoSetup 5.5.5 (and perhaps other versions), just pass whatever you want as a parameter, prefixed by a /

c:\> myAppInstaller.exe /foo=wiggle

and in your myApp.iss:

[Setup]
AppName = {param:foo|waggle}

The |waggle provides a default value if no parameter matches. Inno setup is not case sensitive. This is a particularly nice way to handle command line options: They just spring into existence. I wish there was as slick a way to let users know what command line parameters the installer cares about.

BTW, this makes both @knguyen's and @steve-dunn's answers somewhat redundant. The utility functions do exactly what the built-in {param: } syntax does.

StayOnTarget
  • 11,743
  • 10
  • 52
  • 81
Dan Locks
  • 547
  • 4
  • 5
  • 1
    @TLama: You're right. I had conflated pre-processor options with setup options in my head. – Dan Locks Feb 09 '15 at 23:03
  • Is there a way to take advantage of that mechanism in code? I can only make it work in the [Setup] section, but can you use it in the [Script] section somehow? – NickG Feb 11 '15 at 12:22
  • 1
    @NickG, yes, every constant you can expand by the `ExpandConstant` function. – TLama Feb 12 '15 at 09:49
  • 1
    For a use of `ExpandConstant` with `{param}` constant, see my answer https://stackoverflow.com/a/48349992/850848 – Martin Prikryl Jan 19 '18 at 21:59
18

Further to @DanLocks' answer, the {param:*ParamName|DefaultValue*} constant is documented near the bottom of the Constants page:

http://www.jrsoftware.org/ishelp/index.php?topic=consts

I found it quite handy for optionally suppressing the license page. Here is all I needed to add (using Inno Setup 5.5.6(a)):

[code]
{ If there is a command-line parameter "skiplicense=true", don't display license page }
function ShouldSkipPage(PageID: Integer): Boolean;
begin
  Result := False
  if PageId = wpLicense then
    if ExpandConstant('{param:skiplicense|false}') = 'true' then
      Result := True;
end;
StayOnTarget
  • 11,743
  • 10
  • 52
  • 81
Mark Berry
  • 17,843
  • 4
  • 58
  • 88
18

Inno Setup directly supports switches with syntax /Name=Value using {param} constant.


You can use the constant directly in sections, though this use is quite limited.

An example:

[Registry]
Root: HKCU; Subkey: "Software\My Company\My Program\Settings"; ValueType: string; \
    ValueName: "Mode"; ValueData: "{param:Mode|DefaultMode}"

You will more likely want to use switches in Pascal Script.

If your switch has the syntax /Name=Value, the easiest way to read its value is using ExpandConstant function.

For example:

if ExpandConstant('{param:Mode|DefaultMode}') = 'DefaultMode' then
begin
  Log('Installing for default mode');
end
  else
begin
  Log('Installing for different mode');
end;

If you want to use a switch value to toggle entries in sections, you can use Check parameter and a auxiliary function, like:

[Files]
Source: "Client.exe"; DestDir: "{app}"; Check: SwitchHasValue('Mode', 'Client')
Source: "Server.exe"; DestDir: "{app}"; Check: SwitchHasValue('Mode', 'Server')
[Code]

function SwitchHasValue(Name: string; Value: string): Boolean;
begin
  Result := CompareText(ExpandConstant('{param:' + Name + '}'), Value) = 0;
end;

Ironically it is more difficult to check for a mere presence of switch (without a value).

Use can use a function CmdLineParamExists from @TLama's answer to Passing conditional parameter in Inno Setup.

function CmdLineParamExists(const Value: string): Boolean;
var
  I: Integer;  
begin
  Result := False;
  for I := 1 to ParamCount do
    if CompareText(ParamStr(I), Value) = 0 then
    begin
      Result := True;
      Exit;
    end;
end;

You can obviously use the function in Pascal Script:

if CmdLineParamExists('/DefaultMode') then
begin
  Log('Installing for default mode');
end
  else
begin
  Log('Installing for different mode');
end;

But you can even use it in sections, most typically using Check parameter:

[Files]
Source: "MyProg.hlp"; DestDir: "{app}"; Check: CmdLineParamExists('/InstallHelp')

A related problem:
Add user defined command line parameters to /? window

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
  • 2
    An awesome answer, just what I needed. Thank you for taking the time to write all the useful code snippets for various scenarios! – Violet Giraffe Sep 07 '20 at 13:22
9

This is the function I wrote, which is an improvement of Steven Dunn's answer. You can use it as:

c:\MyInstallDirectory>MyInnoSetup.exe /myParam="parameterValue"
myVariable := GetCommandLineParam('/myParam');
{ util method, equivalent to C# string.StartsWith }
function StartsWith(SubStr, S: String): Boolean;
begin
  Result:= Pos(SubStr, S) = 1;
end;

{ util method, equivalent to C# string.Replace }
function StringReplace(S, oldSubString, newSubString: String): String;
var
  stringCopy: String;
begin
  stringCopy := S; { Prevent modification to the original string }
  StringChange(stringCopy, oldSubString, newSubString);
  Result := stringCopy;
end;

{ ================================================================== }
function GetCommandlineParam(inParamName: String): String; 
var
   paramNameAndValue: String;
   i: Integer;
begin
   Result := '';

   for i := 0 to ParamCount do
   begin
     paramNameAndValue := ParamStr(i);
     if (StartsWith(inParamName, paramNameAndValue)) then
     begin
       Result := StringReplace(paramNameAndValue, inParamName + '=', '');
       break;
     end;
   end;
end;
Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
knguyen
  • 519
  • 6
  • 13
  • 1
    This works great. I only added code to automatically append a '/' to the inParamName value, if it doesn't already start with it. This way I only need to specify the parameter name, and don't have to worry about the correct parameter name prefix when getting the parameter value. – Dragoljub Ćurčić Dec 02 '13 at 13:13
  • 2
    These answers are fine, but with multiple parameters, determining `ParamCount` is another consideration. That's why `ExpandConstant` is so much easier. – Laurie Stearn Jan 19 '18 at 13:09
  • 1
    As @LaurieStearn correctly commented, you can use `ExpandConstant ` to achieve the same with a single line of code. See my answer: https://stackoverflow.com/a/48349992/850848 – Martin Prikryl Jan 19 '18 at 21:49
9

If you want to parse command line arguments from code in inno, then use a method similar to this. Just call the inno script from the command line as follows:

c:\MyInstallDirectory>MyInnoSetup.exe -myParam parameterValue

Then you can call the GetCommandLineParam like this wherever you need it:

myVariable := GetCommandLineParam('-myParam');
{ ================================================================== }
{ Allows for standard command line parsing assuming a key/value organization }
function GetCommandlineParam (inParam: String):String;
var
  LoopVar : Integer;
  BreakLoop : Boolean;
begin
  { Init the variable to known values }
  LoopVar :=0;
  Result := '';
  BreakLoop := False;

  { Loop through the passed in arry to find the parameter }
  while ( (LoopVar < ParamCount) and
          (not BreakLoop) ) do
  begin
    { Determine if the looked for parameter is the next value }
    if ( (ParamStr(LoopVar) = inParam) and
         ( (LoopVar+1) <= ParamCount )) then
    begin
      { Set the return result equal to the next command line parameter }
      Result := ParamStr(LoopVar+1);

      { Break the loop }
      BreakLoop := True;
    end;

    { Increment the loop variable }
    LoopVar := LoopVar + 1;
  end;
end;
Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
Steven Dunn
  • 195
  • 2
  • 2
7

Yes it is possible, you can use the ParamStr function in PascalScript to access all the commandline parameters. The ParamCount function will give you the number of commandline parameters.

Another possibility is to use GetCmdTail

Otherside
  • 2,805
  • 22
  • 21
0

In response to:

"With InnoSetup 5.5.5 (and perhaps other versions), just pass whatever you want as a parameter, prefixed by a /" "@NickG, yes, every constant you can expand by the ExpandConstant function"

  • This is not the case. Trying to use a command line parameter in ExpandConstant in InnoSetup 5.5.6 results in a runtime error.

PS: I would have added a comment directly but apparently I dont have enough "reputation"

Sloth
  • 1
  • 1
  • Works for me in 5.5.6(a). Constants have very strange syntax, though; you have to surround them with single quotation marks inside the ExpandConstant function call. See my answer for an example. – Mark Berry Jan 30 '16 at 00:27
0

I've modified a little bit knguyen's answer. Now it's case insensitive (you can write en console /myParam or /MYPARAM) and it can accept default value. Also I fixed the case when you receive larger parameter then expected (for ex: /myParamOther="parameterValue" in place of /myParam="parameterValue". Now myParamOther doesn't match).

function GetCommandlineParam(inParamName: String; defaultParam: String): String; 
var
   paramNameAndValue: String;
   i: Integer;
begin
   Result := defaultParam;

   for i := 0 to ParamCount do
   begin
     paramNameAndValue := ParamStr(i);
     if  (Pos(Lowercase(inParamName)+'=', AnsiLowercase(paramNameAndValue)) = 1) then
     begin
       Result := Copy(paramNameAndValue, Length(inParamName)+2, Length(paramNameAndValue)-Length(inParamName));
       break;
     end;
   end;
end;
Irina Leo
  • 79
  • 1
  • 2
  • Martin, thank you very much. It really works, but with this syntax ExpandConstant('{param:name|defaultvalue}') – Irina Leo Jan 16 '18 at 14:07
  • OK, true, so fixing my command: While this would work, it's totally unnecessary, as other answers show that you can use `ExpandConstant('{param:name|defaultvalue}')` to achieve exactly the same functionality. – Martin Prikryl Jan 16 '18 at 14:10
  • @MartinPrikryl: With ExpandConstant('{param:name|defaultvalue}'), I can expand defaultValue only if its const, correct? In my case, defaultValue gets computed dynamically in my script based on some conditions. so how can i use that value within Expandconstant to be used if there is no command line parameter ? – jamilia Jul 17 '20 at 16:47
  • @jamilia No, the value can be computed. It's a string argument to a function. Nothing prevents you from "computing" the string value. Though this is not a chat. Please post a new separate question for your new problem. – Martin Prikryl Jul 19 '20 at 19:21
-1

I found the answer: GetCmdTail.

Similar
  • 407
  • 1
  • 4
  • 4
-1

You can pass parameters to your installer scripts. Install the Inno Setup Preprocessor and read the documentation on passing custom command-line parameters.

Bernard
  • 7,908
  • 2
  • 36
  • 33
  • 1
    The preprocessor code is processed before the installer is compiled, so it can't be used to check the commandline parameters of the resulting setup.exe. – Otherside Sep 01 '10 at 13:25
  • I know, which is why I specified "installer scripts" and not the compiled installer executable. I've often needed to do this, so I thought I'd mention this possibility. – Bernard Sep 01 '10 at 13:40