Recursion 使用Inno Setup预处理器获取源路径及其子路径的文件和大小

Recursion 使用Inno Setup预处理器获取源路径及其子路径的文件和大小,recursion,preprocessor,inno-setup,filesize,directory,Recursion,Preprocessor,Inno Setup,Filesize,Directory,我可以使用Inno Setup预处理器获取源路径及其子路径的文件和大小吗 我正在做一个批处理编译器,我需要在[Setup]磁盘中自动设置大小,包括True或False 只能得到源的大小 有人能帮我吗 好的,这有点陈旧,但我想分享我的解决方案,因为我遇到了同样的问题,并找到了某种解决方案: #define FindHandle #define FindResult #dim InnerMask[65536] #define InnerMask[0] "" #define size 0

我可以使用Inno Setup预处理器获取源路径及其子路径的文件和大小吗

我正在做一个批处理编译器,我需要在[Setup]磁盘中自动设置大小,包括True或False

只能得到源的大小

有人能帮我吗



好的,这有点陈旧,但我想分享我的解决方案,因为我遇到了同样的问题,并找到了某种解决方案:

#define FindHandle
#define FindResult 
#dim InnerMask[65536]
#define InnerMask[0] ""
#define size 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
            #define Public size size + FileSize(FileName)
        #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 RunSizeScan
    #define Public InnerMaskPosition 1
    #define Public InnerMaskWorkPosition 0
    #expr size=0
    #for {InnerMaskWorkPosition = 0; InnerMaskWorkPosition < InnerMaskPosition; InnerMaskWorkPosition++} ProcessInnerMaskPosition
    #undef Public InnerMaskPosition
    #undef Public InnerMaskWorkPosition
#endsub

#expr InnerMask[0]="some-dir-name-you-want-the-size-of\"
#expr RunSizeScan

#if size > 2100000000
    #define Span "True"
#else
    #define Span "False"
#endif
#定义FindHandle
#定义FindResult
#昏暗的内遮罩[65536]
#定义内部掩码[0]“”
#定义大小0
#子进程文件
#定义InnerFileName FindGetFileName(FindHandle)
#定义文件名InnerMask[InnerMaskWorkPosition]+InnerFileName
#如果是InnerFileName=“&&InnerFileName=".."
#如果存在目录(文件名)
#定义公共InnerMask[InnerMaskPosition]文件名+“\”
#定义公共InnerMaskPosition InnerMaskPosition+1
#否则
#定义公共大小+文件大小(文件名)
#恩迪夫
#恩迪夫
#endsub
#子进程InnerMaskPosition
#对于{FindHandle=FindResult=FindFirst(内部掩码[InnerMaskWorkPosition]+“*”,faAnyFile);FindResult;FindResult=FindNext(FindHandle)}ProcessFoundFile
#如果FindHandle
#expr FindClose(FindHandle)
#恩迪夫
#endsub
#次运行尺寸扫描
#定义公共InnerMaskPosition 1
#定义公共InnerMaskWorkPosition 0
#expr size=0
#对于{InnerMaskWorkPosition=0;InnerMaskWorkPosition210000000
#定义Span“True”
#否则
#定义Span“False”
#恩迪夫
它所做的是扫描数组“InnerMask”中给定的目录,查找不是“.”或“.”的所有内容。将文件添加到已计算的大小,并将目录添加到数组“InnerMask”。一旦不再有子目录需要计算,此过程将结束


注意:由于数组的限制设置为65536,所以在扫描目录中嵌套的文件夹数量不应超过此数量。否则,您可以尝试重用第一个已处理的阵列插槽或使用多个阵列。

这是递归版本,为便于阅读,它分为几个宏:

#define private CalcDirSize(str path, int size = 0) \
    CalcFileSize(path, FindFirst(AddBackSlash(path) + '*.*', faAnyFile), size)

#define private CalcFileSize(str path, int handle, int size) \
    handle ? CalcFileSizeFilterPath(path, handle, size) : size

#define private CalcFileSizeFilterPath(str path, int handle, int size) \
    FindGetFilename(handle) == '.' || FindGetFilename(handle) == '..' ? \
        GoToNextFile(path, handle, size) : \
        CalcFileSizeTestIfDir(path, handle, size, AddBackSlash(path) + FindGetFilename(handle))

#define private GoToNextFile(str path, int handle, int size) \
    FindNext(handle) ? CalcFileSizeFilterPath(path, handle, size) : size

#define private CalcFileSizeTestIfDir(str path, int handle, int size, str filename) \
    DirExists(filename) ? CalcDirSize(filename) + GoToNextFile(path, handle, size) : \
        GoToNextFile(path, handle, size + FileSize(filename))

不支持太多的文件(糟糕的ISPP将耗尽内存)或较大的文件(>2gb),但它应该适合较小的设置。

您知道该函数仅为2gb以下的文件返回正确的值吗?无论如何,好问题!很抱歉,我忘了设置相反的条件。我担心这不是不可能的,就是非常困难的任务,因为似乎没有办法编写递归(因为在子例程中没有子例程),而对于非递归方式,您无法编写循环(因为没有
while
循环可用,并且
for
循环在进入循环时评估其条件)。但也许我错了……我还想到了其他子例程,总是给出主目录的大小
FindFirst
FindNext
的本质是列出文件(和/或目录)从给定的路径。它不包括子目录中的项。您需要列出所有子目录,并为每个子目录调用一个类似于您的例程。由于语法上的限制,我不知道如何以常规方式编写它来列出所有级别的子目录。对于给定的深度级别,它非常容易…确实非常好!H但是,它返回的结果不正确。我尝试用随机放置的40B文件创建一些子目录,结果相差8字节(预处理器计算的大小较小)。与另一个文件夹不同的是152字节,与以前一样,这是一个可被8整除的数字。这很奇怪,并指出
FileSize
函数可能存在问题。[不幸的是,我没有时间深入研究这个deeeper]啊,有问题了。文件夹的文件大小等于-1,如果对名为“.”或“…”的目录进行求值,它将跳转到else分支。将编辑我的解决方案。哦,那么这8只是巧合。感谢更新![已投票]
#define private CalcDirSize(str path, int size = 0) \
    CalcFileSize(path, FindFirst(AddBackSlash(path) + '*.*', faAnyFile), size)

#define private CalcFileSize(str path, int handle, int size) \
    handle ? CalcFileSizeFilterPath(path, handle, size) : size

#define private CalcFileSizeFilterPath(str path, int handle, int size) \
    FindGetFilename(handle) == '.' || FindGetFilename(handle) == '..' ? \
        GoToNextFile(path, handle, size) : \
        CalcFileSizeTestIfDir(path, handle, size, AddBackSlash(path) + FindGetFilename(handle))

#define private GoToNextFile(str path, int handle, int size) \
    FindNext(handle) ? CalcFileSizeFilterPath(path, handle, size) : size

#define private CalcFileSizeTestIfDir(str path, int handle, int size, str filename) \
    DirExists(filename) ? CalcDirSize(filename) + GoToNextFile(path, handle, size) : \
        GoToNextFile(path, handle, size + FileSize(filename))