Inno Setup - 在不创建相同子目录的情况下递归子目录

时间:2016-04-20 11:38:23

标签: inno-setup

我经常使用recursesubdirs标志遍历多个子目录并提取特定文件或文件类型,而无需单独显式引用每个文件。例如:

Source: C:\kh25\dependencies\*.dll; DestDir: {app}; Flags: recursesubdirs

这将在我的目标{app}路径中创建与最初从中检索DLL的源完全相同的目录结构。例如,如果我从上面的C:\kh25\dependencies\test检索了一个DLL,那么它会将该DLL放在{app}\test路径中。

可以通过以下方式修改此行为:

Source: C:\kh25\dependencies\test\*.dll; DestDir: {app}; Flags: recursesubdirs

但显然这意味着我必须单独引用依赖项中的每个子目录。

64,000美元的问题是如何防止在目的地中重新创建同一目录而不必显式引用源目录?

1 个答案:

答案 0 :(得分:1)

使用Inno Setup preprocessor生成[Files]部分的条目。

一种可能(而且相对简单和简单)的解决方案是使用递归宏,如:

#pragma parseroption -p-

#define FileEntry(Source) \
    "Source: " + Source + "; DestDir: {app}\n"

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

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

#pragma parseroption -p+

#emit ProcessFolder("C:\kh25\dependencies")

虽然这个解决方案有其局限性,但可能会使具有大量文件或深层目录结构的预处理器崩溃(适用于数千个文件)。

灵感来自answer by @Zlatko KarakašUse Inno Setup PreProcessor to get the files and size of the source path and its subdirs

更可靠(丑陋和复杂)的解决方案是使用用户定义的程序。它很复杂,因为预处理器缺乏对用户定义过程参数的支持。

[Files]

#define FindHandle
#define FindResult 
#dim InnerMask[65536]
#define InnerMask[0] ""

#sub ProcessFoundFile
    #define InnerFileName FindGetFileName(FindHandle)
    #define fileName InnerMask[InnerMaskWorkPosition] + InnerFileName
    #if InnerFileName!="." && InnerFileName!=".."
        #if DirExists(FileName)
            #define Public InnerMask[InnerMaskPosition] FileName+"\"
            #define Public InnerMaskPosition InnerMaskPosition + 1
        #else
            Source: {#FileName}; DestDir: {app}
        #endif
    #endif 
#endsub

#sub ProcessInnerMaskPosition 
    #for { \
        FindHandle = FindResult = \
            FindFirst(InnerMask[InnerMaskWorkPosition]+"*", faAnyFile); \
        FindResult; FindResult = FindNext(FindHandle)} ProcessFoundFile
    #if FindHandle
        #expr FindClose(FindHandle)
    #endif
#endsub

#sub CollectFiles
    #define Public InnerMaskPosition 1
    #define Public InnerMaskWorkPosition 0
    #for { \
        InnerMaskWorkPosition = 0; InnerMaskWorkPosition < InnerMaskPosition; \
            InnerMaskWorkPosition++} \
            ProcessInnerMaskPosition
    #undef Public InnerMaskPosition
    #undef Public InnerMaskWorkPosition
#endsub

#expr InnerMask[0]="C:\kh25\dependencies\"
#expr CollectFiles

answer by @René MartinUse Inno Setup PreProcessor to get the files and size of the source path and its subdirs的递归扫描功能。

在Inno Setup脚本的 very end 上添加SaveToFile调用,看看预处理器生成的内容:

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

请参阅Inno Setup: How do I see the output (translation) of the Inno Setup Preprocessor?