Inno Setup-递归子目录而不创建那些相同的子目录
我经常使用recursesubdirs
标志来遍历多个子目录并提取特定文件或文件类型,而不必显式地分别引用每个文件.示例:
I often use the recursesubdirs
flag to traverse through a number of sub directories and extract a specific file or type of file without having to explicitly refer to each file individually. Example:
Source: C:\kh25\dependencies\*.dll; DestDir: {app}; Flags: recursesubdirs
这将在我的目标{app}
路径中创建与最初从中检索DLL的源完全相同的目录结构.例如,如果我从上面的C:\kh25\dependencies\test
中检索了一个DLL,则它将将该DLL放置在{app}\test
路径中.
This creates the exact same directory structure in my destination {app}
path as the source from where the DLL was initially retrieved from. For example if I retrieved a DLL from C:\kh25\dependencies\test
above then it would place that DLL in the {app}\test
path.
可以通过执行以下操作来修改此行为:
This behaviour can be modified by doing this:
Source: C:\kh25\dependencies\test\*.dll; DestDir: {app}; Flags: recursesubdirs
但是显然,这意味着我将不得不分别引用依赖项中的每个子目录.
But obviously this means I would have to reference each sub directory in dependencies individually.
所以$ 64,000的问题是如何防止在不必显式引用源目录的情况下在目标中重新创建同一目录?
So the $64,000 question is how can I prevent the same directory from being recreated in the destination without having to explicitly reference the source directory?
使用 Inno Setup预处理器生成[Files]
部分的条目.
一种可能的(且相对简单易用)的解决方案是使用递归宏,例如:
One possible (and relatively nice and simple) solution is using a recursive macro like:
#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")
尽管此解决方案有其局限性,并且可能会使预处理器崩溃,因为它包含大量文件或深层目录结构(可以处理数千个文件).
Though this solution has its limit and may crash the preprocessor with large number of files or deep directory structure (works ok for thousands of files).
由由@ZlatkoKarakaš答复为更可靠(又丑陋又复杂)的解决方案是使用用户定义的过程.这很复杂,因为预处理器不支持用户定义过程的参数.
More reliable (and ugly and complex) solution is using a user defined procedures. It's complicated because the preprocessor lacks a support for parameters of user-defined procedures.
[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éMartin 到在末尾添加 SaveToFile
调用您的Inno Setup脚本也可以看到预处理器生成的内容:
Add a SaveToFile
call at the very end of your Inno Setup script too see, what the preprocessor generates:
#expr SaveToFile(AddBackslash(SourcePath) + "Preprocessed.iss")
请参见 Inno设置:如何查看Inno设置预处理器的输出(翻译)?
我对这个问题的回答解释了以上两种方法之间的区别:
是否可以使用Inno Setup预处理器来构建重复的自定义消息集?
My answer to this question explains the differences between the two approaches taken above:
Can Inno Setup Preprocessor be used to build a duplicated set of custom messages?