Inno Setup:为文件夹及其子文件夹中的所有文件动态添加组件

Posted

技术标签:

【中文标题】Inno Setup:为文件夹及其子文件夹中的所有文件动态添加组件【英文标题】:Inno Setup: Dynamically add a component for all files in a folder and its subfolders 【发布时间】:2017-12-16 23:15:14 【问题描述】:

Inno Setup:动态添加文件夹中的所有文件并添加组件标签,因此在运行设置期间用户可以选择自定义设置并选择要复制的文件。

我想创建一个 Inno Setup 文件,该文件将抓取用户可以放入其中的文件夹中的文件,而无需在每次添加新文件时修改 Inno Setup 文件。同时,我需要安装文件的用户能够选择要复制的文件。

如果我这样做:

Source: "D:\SomeDirectory\*"; DestDir: "app"; \
   Flags: ignoreversion recursesubdirs createallsubdirs; Components: dlls

自定义设置仅显示复制或不复制整个文件夹的选项。

【问题讨论】:

"文件夹中的文件" - 什么文件夹?编译时还是运行时? 你需要递归吗? 【参考方案1】:

假设文件在编译时可用,您可以使用Inno Setup Preprocessor 递归宏来生成[Files][Components] 部分。

此代码部分基于Generating Inno Setup file flags programmatically。

#pragma parseroption -p-

#define FileEntry(Source, Dest) \
    Local[0] = Copy(Dest, 2, Len(Dest) - 1), \
    Local[1] = StringChange(Local[0], ".", ""), \
    "[Files]\n" + \
    "Source: " + Source + "; DestDir: app" + ExtractFileDir(Dest) + \
        "; Components: " + Local[1] + "\n" + \
    "[Components]\n" + \
    "Name: " + Local[1] + "; Description: " + ExtractFileName(Dest) + "\n"

#define DirEntry(Source, Dest) \
    Local[0] = Copy(Dest, 2, Len(Dest) - 1), \
    Local[1] = StringChange(Local[0], ".", ""), \
    "[Components]\n" + \
    "Name: " + Local[1] + "; Description: " + ExtractFileName(Dest) + "\n"

#define ProcessFile(Source, Dest, FindResult, FindHandle) \
    FindResult \
        ? \
            Local[0] = FindGetFileName(FindHandle), \
            Local[1] = Source + "\\" + Local[0], \
            Local[2] = Dest + "\\" + Local[0], \
            (Local[0] != "." && Local[0] != ".." \
                ? (DirExists(Local[1]) \
                     ? DirEntry(Local[1], Local[2]) + ProcessFolder(Local[1], Local[2]) \
                     : FileEntry(Local[1], Local[2])) \
                : "") + \
            ProcessFile(Source, Dest, FindNext(FindHandle), FindHandle) \
        : \
            ""

#define ProcessFolder(Source, Dest) \
    Local[0] = FindFirst(Source + "\\*", faAnyFile), \
    ProcessFile(Source, Dest, Local[0], Local[0])

#pragma parseroption -p+

#emit ProcessFolder("D:\SomeDirectory", "")

如果D:\SomeDirectory 包含这些文件:

file1.txt
file2.txt
sub1\file11.txt
sub1\file12.txt
sub2\file21.txt
sub2\file22.txt

上面的代码会生成:

[Files]
Source: D:\SomeDirectory\file1.txt; DestDir: app; Components: file1txt
[Components]
Name: file1txt; Description: file1.txt
[Files]
Source: D:\SomeDirectory\file2.txt; DestDir: app; Components: file2txt
[Components]
Name: file2txt; Description: file2.txt
[Components]
Name: sub1; Description: sub1
[Files]
Source: D:\SomeDirectory\sub1\file11.txt; DestDir: app\sub1; Components: sub1\file11txt
[Components]
Name: sub1\file11txt; Description: file11.txt
[Files]
Source: D:\SomeDirectory\sub1\file12.txt; DestDir: app\sub1; Components: sub1\file12txt
[Components]
Name: sub1\file12txt; Description: file12.txt
[Components]
Name: sub2; Description: sub2
[Files]
Source: D:\SomeDirectory\sub2\file21.txt; DestDir: app\sub2; Components: sub2\file21txt
[Components]
Name: sub2\file21txt; Description: file21.txt
[Files]
Source: D:\SomeDirectory\sub2\file22.txt; DestDir: app\sub2; Components: sub2\file22txt
[Components]
Name: sub2\file22txt; Description: file22.txt

在安装程序中,您将获得:


请注意,您可以通过这种方式处理的文件数量受预处理器堆栈的限制。

如果你被它击中,另一种(虽然丑陋和复杂)的方法是使用用户定义的过程。有关使用此处显示的方法和使用用户定义的过程来实现递归文件处理的示例,请参阅Inno Setup - Recurse sub directories without creating those same sub directories。

【讨论】:

这正是我想要的,而且效果很好!谢谢。 跟进这个,试图弄清楚如何添加文件扩展名必须是dll的要求。 我想通了!第 39 行 (Local[0] != "." && Local[0] != ".." && 小写(ExtractFileExt(Local[0])) == "dll" \

以上是关于Inno Setup:为文件夹及其子文件夹中的所有文件动态添加组件的主要内容,如果未能解决你的问题,请参考以下文章

关于Inno Setup卸载程序删除文件夹的问题

防止 Inno Setup 在卸载时删除某些文件

Inno Setup:包含所有子文件夹的打包文件夹

NSIS 或 Inno Setup打包软件如何得到当前文件名

Inno Setup 中的文件关联

Inno Setup安装前删除旧文件和文件夹