Inno Setup: Dynamically add a component for all files in a folder and its subfolders

前端 未结 1 1574
盖世英雄少女心
盖世英雄少女心 2020-12-10 09:42

Inno Setup: Dynamically add all files in a folder and add a component tag, so during running of the setup the user can select custom setup and select which files to copy.

相关标签:
1条回答
  • 2020-12-10 10:04

    Assuming the files are available on compile time, you can use Inno Setup Preprocessor recursive macro to generate the [Files] and [Components] sections.

    This code is partially based on 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", "")
    

    If D:\SomeDirectory contains these files:

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

    The above code will generate:

    [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
    

    In installer, you will get:


    Though note that number of files you can process this way is limited by preprocessor stack.

    If you get hit by that, the other (though ugly and complex) way is to use user defined procedures. For an example of implementing a recursive files processing both using approach shown here and using user defined procedures, see Inno Setup - Recurse sub directories without creating those same sub directories.

    0 讨论(0)
提交回复
热议问题