【问题标题】:Inno Setup - Automatically generate options to allow user to choose what files to installInno Setup - 自动生成选项以允许用户选择要安装的文件
【发布时间】:2020-03-09 10:41:44
【问题描述】:

我正在使用 Inno Setup 工具以这种方式安装一些程序及其关联的宏:

[Files]
Source: "..\macros\*.js"; DestDir: "{app}\macros"; Flags: ignoreversion

现在我想做的是让用户选择一部分宏,而不是全部安装。例如,我想在安装过程中显示一个自定义复选框页面,用户可以在其中选择他想安装的宏(额外的“全选”、“全选”快捷按钮会很棒)。

你知道我可以从中获得启发的任何类似案例/示例 Inno Setup-script 吗?

NB1:我不知道..\macros\ 文件夹中有多少个宏,也不知道它们的名称,所以我无法在[Files] 部分中一一列出。

NB2:我已经阅读了这个帖子,但这不是我真正想要的(需要在 macros 文件夹中的任何更改上更新 .iss,这不是一个聪明的解决方案):How can I add a CheckBox for optional files during install? (innosetup)

【问题讨论】:

  • Inno Setup: Dynamically add a component for all files in a folder and its subfolders——你的代码实际上可以更简单,因为你不需要它递归到子目录。
  • @MartinPrikryl 听起来不错,到目前为止,我遇到编译器错误,将 emit 替换为我自己的文件夹 #emit ProcessFolder("..\macros", "") ...需要进一步研究...错误消息是“参数“名称”包含无效字符”
  • 尝试使用绝对路径。如果你不让它工作,请发帖minimal reproducible example
  • @MartinPrikryl 我想我明白了...错误不是来自绝对/相对路径,而是来自包含括号[ ] 的宏的名称...请参见此处的图片:@ 987654324@ ... 如果文件夹仅包含 macro1.js 一切正常,但添加 [MyTool] - macro2.js 会产生问题。
  • 好的,你需要让它处理这些文件吗?或者你可以重命名它们吗?

标签: inno-setup


【解决方案1】:

如果您想提前定义一些宏“组”(而不是让它们可以单独选择),那么您可以简单地将源文件排列到这些组中,然后相应地设置组件:

[Components]
Name: macroX; Description: "Macros for X"
Name: macroY; Description: "Macros for Y"

[Files]
Source: "..\macros\macroX\*.js"; DestDir: "{app}\macros"; Components: macroX; Flags: ignoreversion
Source: "..\macros\macroY\*.js"; DestDir: "{app}\macros"; Components: macroY; Flags: ignoreversion

也可以在这些组中进行单独选择,但您必须单独命名文件:

[Components]
Name: macroX\macro1; Description: "Macro1"
[Files]
Source: "..\macros\macroX\macro1.js"; DestDir: "{app}\macros"; Components: macroX\macro1; Flags: ignoreversion

可以使用 ISPP 使用通配符生成上述代码,但这留给读者作为练习。


最后,您可以使用[Types] 来提供全选/全选功能:

[Setup]
AlwaysShowComponentsList=yes
[Types]
Name: all; Description: "All macros"
Name: none; Description: "No macros"
Name: custom; Description: "Custom selection"; Flags: iscustom

然后将Types: all 放在您的所有[Components] 条目上。

【讨论】:

  • 我所拥有的有效设置比问题中的示例更复杂一点,现在像这样重新排列,但是使用 ISPP 是的,正如@MartinPrikril 所示,这将是一种优雅的组织方式。谢谢
【解决方案2】:

@MartinPrikryl 在问题 cmets 中提出并详细描述in this other thread 的使用预处理器指令和代码发射的解决方案是一个非常好的解决方案,我肯定会推荐它。

无论如何,这里有一些仅使用 Pascal 脚本的替代方案:

  1. 首先我让安装程序安装所有宏,但我在[File] 部分中使用AfterInstall 处理程序来监视它们:

    [Files]
    Source: ".\macros\*.txt"; DestDir: "{app}\macros"; Flags: ignoreversion; AfterInstall: AfterInstallEachMacro;
    
  2. 处理程序AfterInstallEachMacro 只是将所有宏记录在[Code] 部分的全局变量中,并填充一些额外的向导页面,这些页面将在安装完成后显示:

    procedure AfterInstallEachMacro();
    var 
      filename : String; 
    begin
    
      filename := CurrentFileName;
      filename := ExpandConstant(filename);
      GMacrosFullFilenames.Add(filename);
    
      filename := ExtractFileName(filename);  
      GMacrosSelectectionPage.Add(filename);
      GMacrosSelectectionPage.Values[GMacrosTotalCount] := True;
      GMacrosTotalCount := GMacrosTotalCount + 1;
    
    end;
    
  3. 最后,离开最后一个向导页面后,我只需删除用户未选择的宏:

    function NextButtonClick(CurPageID: Integer): Boolean;
      var index: Integer;
    begin
      Result := true; 
    
      {* When leaving page for macro selection *}
      if (CurPageID = GMacrosSelectectionPage.ID) then begin
    
        {* Delete macros the user do not want *}
        for index := 0 to (GMacrosTotalCount - 1) do 
        begin
          if (not(GMacrosSelectectionPage.Values[index])) then begin
            DeleteFile(GMacrosFullFilenames[index]);
          end;
        end;
    
      end;
    end;
    

这种方法可能不太优雅或可以进一步改进,但比@MartinPrikryl 提出的solution 更适合我的特定情况。

完整的 innoscript 托管在 here。下面是它的样子:

【讨论】:

  • 假设GMacrosFullFilenamesTStrings/TStringList,则可以使用GMacrosFullFilenames.Count,不需要GMacrosTotalCount
  • @MartinPrikryl 确实你是对的......这个解决方案的主要问题是安装后(没有返回按钮)并且到目前为止不完整(没有全选/无).. .您的解决方案更优雅(尽管在我的实践中更复杂的情况下,如果不深入改变我已经拥有的安装范例,我无法看到如何将这些宏文件转换为组件或任务)。非常感谢您的帮助和想法。
猜你喜欢
  • 2011-08-01
  • 2012-05-07
  • 1970-01-01
  • 2021-09-15
  • 2010-09-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多