Inno setup Inno Setup-递归子目录而不创建相同的子目录

Inno setup Inno Setup-递归子目录而不创建相同的子目录,inno-setup,Inno Setup,我经常使用recursesubdirs标志遍历多个子目录并提取特定文件或文件类型,而不必单独显式引用每个文件。例如: Source: C:\kh25\dependencies\*.dll; DestDir: {app}; Flags: recursesubdirs 这将在我的目标{app}路径中创建与最初从中检索DLL的源路径完全相同的目录结构。例如,如果我从上面的C:\kh25\dependencies\test中检索到一个DLL,那么它会将该DLL放在{app}\test路径中 可以通过以

我经常使用
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
但显然,这意味着我必须单独引用依赖项中的每个子目录

因此$64000的问题是,如何防止在目标中重新创建相同的目录,而不必显式引用源目录?

用于生成
[文件]
部分的条目

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

#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")
尽管此解决方案有其局限性,并且可能会使具有大量文件或深层目录结构的预处理器崩溃(适用于数千个文件)

灵感来源于《到》


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

[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


我对这个问题的回答解释了上述两种方法之间的差异:

谢谢你,马丁。工作比我希望的多,但我想你不可能赢得所有的工作。
#expr SaveToFile(AddBackslash(SourcePath) + "Preprocessed.iss")