【问题标题】:Array variables and dynamic access in [Code] section[代码] 部分中的数组变量和动态访问
【发布时间】:2022-08-21 04:16:21
【问题描述】:

我的安装程序有Components,它与可下载文件相关联。这些东西随着构建而变化,所以我使用#insert 创建[Components] 部分以及[Files] 部分中的相应条目。 其中一些组件依赖于常见的可下载文件。

现在,为了在下载页面中包含正确的 url,我目前正在定义数组变量,这些变量的名称与组件类似,并且具有所需的可下载文件的名称作为值,例如:

#dim myfeature[2] {\"01aed27862e2087bd117e9b677a8685aebb0be09744723b4a948ba78d6011bac\", \"677756ac5969f814fd01ae677dbb832ab2e642513fea44ea0a529430d5ec1fdc\"}

在下载页面的代码中,我正在检查通过WizardSelectedComponents() 选择了哪些组件,并将字符串转换为字符串数组后,我正在尝试访问先前定义的变量,这就是我的位置米失败:

function GetDownloads(): Array of String;
var
  Downloads: Array of String;
  SelectedComponents: String;
  SelectedArray: Array of String;
begin
  SelectedComponents := WizardSelectedComponents(False);
  // a custom procedure to parse the comma seperated string
  SelectedArray := ParseArray(SelectedComponents, SelectedArray);

  // trying to get to the constant array now this works:
  MsgBox(ExpandConstant(\'{#myfeature[0]}\'), mbInformation, MB_OK);

  // same but trying to use the selected component value returns this as a literal
  // \'+SelectedArray[0]+\' instead the expanded value
  MsgBox(ExpandConstant(\'{#\' + SelectedArray[0] + \'[0]}\'), mbInformation, MB_OK);
end;

所以我知道# 标记出了点问题,但我找不到正确解决这个问题的方法。

谢谢! 马库斯

    标签: inno-setup


    【解决方案1】:

    ExpandConstant 扩展 Inno Setup "constants",而不是 preprocessor 值。另见Evaluate preprocessor macro on run time in Inno Setup Pascal Script

    您不能使用运行时索引访问预处理器编译时数组的元素。

    如果您了解 C/C++,就像您尝试做的那样:

    #define VALUE1 123
    #define VALUE2 456
    
    int index = 1;
    int value = VALUE ## index
    

    我不确定我是否完全理解你在做什么。但似乎您需要在编译时从各种来源创建一个数组并在运行时使用它。

    有几种方法可以用于此。但是您肯定需要在运行时初始化运行时数组。但是初始化它的代码可以在编译时生成。

    下面是该方法的一个示例(最后是其他方法的一些链接)。

    在脚本的开头,定义这些支持函数:

    [Code]
    var
      FeatureDownloads: TStrings;
    
    function AddFeature(
      Feature: Integer; CommaSeparatedListOfDownloads: string): Boolean;
    begin
      if not Assigned(FeatureDownloads) then
      begin
        FeatureDownloads := TStringList.Create();
      end;
      while FeatureDownloads.Count <= Feature do
        FeatureDownloads.Add('');
      if FeatureDownloads[Feature] <> '' then
        RaiseException('Downloads for feature already defined');
      FeatureDownloads[Feature] := CommaSeparatedListOfDownloads;
      Result := True;
    end;
    
    #define AddFeature(Feature, CommaSeparatedListOfDownloads) \
      "<event('InitializeSetup')>" + NewLine + \
      "function InitializeSetupFeature" + Str(Feature) + "(): Boolean;" + NewLine + \
      "begin" + NewLine + \
      "  Result := AddFeature(" + Str(Feature) + ", '" + CommaSeparatedListOfDownloads + "');" + NewLine + \
      "end;"
    

    在您的组件包含文件中,执行以下操作:

    #emit AddFeature(2, "01aed27862e2087bd117e9b677a8685aebb0be09744723b4a948ba78d6011bac,677756ac5969f814fd01ae677dbb832ab2e642513fea44ea0a529430d5ec1fdc")
    

    如果添加:

    #expr SaveToFile(AddBackslash(SourcePath) + "Preprocessed.iss")
    

    在主脚本的末尾,您将在预处理器/编译器生成的Preprocessed.iss 中看到#emit directive 扩展为:

    <event('InitializeSetup')>
    function InitializeSetupFeature2(): Boolean;
    begin
      Result := AddFeature(2, '01aed27862e2087bd117e9b677a8685aebb0be09744723b4a948ba78d6011bac,677756ac5969f814fd01ae677dbb832ab2e642513fea44ea0a529430d5ec1fdc');
    end;
    

    现在您有了FeatureDownloads Pascal 脚本运行时变量,您可以使用FeatureDownloads[SelectedArray[0]] 访问它以获取逗号分隔的字符串,您可以将其解析为单独的下载。

    这可以优化/改进很多,但我不知道/了解您的任务范围。但是我相信一旦你掌握了这个概念(一开始可能很难),你就可以自己做。


    另一个类似的问题:

    【讨论】:

    • 谢谢!我不知道我可以在[Code] 部分添加#include 和类似内容。这有很大帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多