【问题标题】:Is it possible to accept custom command line parameters with Inno Setup是否可以使用 Inno Setup 接受自定义命令行参数
【发布时间】:2011-04-06 19:18:39
【问题描述】:

我正在使用 Inno Setup 准备安装程序。但我想添加一个额外的自定义(没有可用参数)命令行参数,并想获取参数的值,例如:

setup.exe /do something

检查是否给出了/do,然后获取某物的值。可能吗?我该怎么做?

【问题讨论】:

    标签: command-line inno-setup command-line-arguments


    【解决方案1】:

    Inno Setup 直接支持使用{param} constant 语法/Name=Value 的开关。


    您可以直接在部分中使用该常量,尽管这种用途非常有限。

    一个例子:

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

    您更有可能希望在Pascal Script 中使用开关。

    如果您的开关具有/Name=Value 语法,则读取其值的最简单方法是使用ExpandConstant function

    例如:

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

    如果要使用开关值来切换部分中的条目,可以使用Check parameter 和辅助功能,例如:

    [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;
    

    具有讽刺意味的是,仅检查是否存在 switch(没有值)更加困难。

    使用可以使用@TLama 对Passing conditional parameter in Inno Setup 的回答中的函数CmdLineParamExists

    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;
    

    你显然可以使用 Pascal Script 中的函数:

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

    但您甚至可以分段使用它,最常见的是使用Check parameter

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

    一个相关问题:
    Add user defined command line parameters to /? window

    【讨论】:

    • 一个很棒的答案,正是我所需要的。感谢您花时间为各种场景编写所有有用的代码 sn-ps!
    【解决方案2】:

    我修改了一点knguyen的答案。现在它不区分大小写(您可以在控制台中编写 /myParam 或 /MYPARAM)并且它可以接受默认值。我还修复了当您收到比预期更大的参数时的情况(例如:/myParamOther="parameterValue" 代替 /myParam="parameterValue"。现在 myParamOther 不匹配)。

    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;
    

    【讨论】:

    • 马丁,非常感谢。它确实有效,但使用此语法 ExpandConstant('{param:name|defaultvalue}')
    • 好的,没错,所以修复我的命令:虽然这可行,但完全没有必要,因为其他答案表明您可以使用 ExpandConstant('{param:name|defaultvalue}') 来实现完全相同的功能。
    • @MartinPrikryl:使用 ExpandConstant('{param:name|defaultvalue}'),我只能在 defaultValue 为 const 的情况下展开它,对吗?就我而言,defaultValue 根据某些条件在我的脚本中动态计算。那么如果没有命令行参数,我如何在 Expandconstant 中使用该值?
    • @jamilia 不,可以计算该值。它是函数的字符串参数。没有什么可以阻止您“计算”字符串值。虽然这不是聊天。请针对您的新问题发布一个新的单独问题。
    【解决方案3】:

    这是我写的函数,是对 Steven Dunn 的回答的改进。您可以将其用作:

    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;
    

    【讨论】:

    • 这很好用。我只添加了代码以自动将“/”附加到 inParamName 值(如果它还没有以它开头)。这样我只需要指定参数名,获取参数值时不用担心参数名前缀是否正确。
    • 这些答案很好,但是有多个参数,确定ParamCount 是另一个考虑因素。这就是ExpandConstant 如此简单的原因。
    • 正如@LaurieSearn 正确评论的那样,您可以使用ExpandConstant 通过一行代码实现相同的目的。看我的回答:stackoverflow.com/a/48349992/850848
    【解决方案4】:

    如果你想从 inno 中的代码解析命令行参数,那么使用类似的方法。只需从命令行调用 inno 脚本,如下所示:

    c:\MyInstallDirectory>MyInnoSetup.exe -myParam parameterValue
    

    然后,您可以在任何需要的地方调用 GetCommandLineParam:

    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;
    

    【讨论】:

    • 我发现这非常有用,但我认为它不支持引用的参数值。
    • @knguyen 的回答很简单,并且可以使用引用的值。
    • 您可以使用ExpandConstant 用一行代码实现相同的目的。看我的回答:stackoverflow.com/a/48349992/850848
    【解决方案5】:

    除了@DanLocks 的回答,{param:ParamName|DefaultValue} 常量记录在常量页面底部附近:

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

    我发现选择性地隐藏许可证页面非常方便。这是我需要添加的所有内容(使用 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;
    

    【讨论】:

      【解决方案6】:

      回应:

      “使用 InnoSetup 5.5.5(可能还有其他版本),只需将任何你想要的作为参数传递,以 / 为前缀” "@NickG,是的,您可以通过 ExpandConstant 函数扩展的每个常量"

      • 情况并非如此。尝试在 InnoSetup 5.5.6 的 ExpandConstant 中使用命令行参数会导致运行时错误。

      PS:我会直接添加评论,但显然我没有足够的“声誉”

      【讨论】:

      • 在 5.5.6(a) 中为我工作。不过,常量有非常奇怪的语法;您必须在 ExpandConstant 函数调用中用单引号将它们括起来。例如,请参阅我的答案。
      【解决方案7】:

      使用 InnoSetup 5.5.5(可能还有其他版本),只需将您想要的任何参数作为参数传递,前缀为 /

      c:\> myAppInstaller.exe /foo=wiggle
      

      在你的 myApp.iss 中:

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

      如果没有参数匹配,|waggle 会提供默认值。 Inno 设置不区分大小写。这是处理命令行选项的一种特别好的方法:它们刚刚出现。我希望有一种巧妙的方法让用户知道安装程序关心的命令行参数。

      顺便说一句,这使得@knguyen 和@steve-dunn 的答案有些多余。实用程序函数的功能与内置 {param: } 语法完全相同。

      【讨论】:

      • @TLama:你是对的。我在脑海中将预处理器选项与设置选项混为一谈。
      • 有没有办法在代码中利用这种机制?我只能在 [Setup] 部分让它工作,但你能在 [Script] 部分以某种方式使用它吗?
      • @NickG,是的,您可以通过ExpandConstant 函数扩展每个常量。
      • 要使用ExpandConstant{param} 常量,请参阅我的答案stackoverflow.com/a/48349992/850848
      【解决方案8】:

      您可以将参数传递给安装程序脚本。安装Inno Setup Preprocessor 并阅读有关传递自定义命令行参数的文档。

      【讨论】:

      • 预处理器代码是在编译安装程序之前处理的,因此不能用于检查生成的setup.exe的命令行参数。
      • 我知道,这就是我指定“安装程序脚本”而不是编译后的安装程序可执行文件的原因。我经常需要这样做,所以我想我会提到这种可能性。
      【解决方案9】:

      是的,您可以使用 PascalScript 中的 ParamStr 函数来访问所有命令行参数。 ParamCount 函数将为您提供命令行参数的数量。

      另一种可能是使用GetCmdTail

      【讨论】:

        【解决方案10】:

        我找到了答案:GetCmdTail。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-02-19
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多