Inno setup Inno安装程序-更新时删除旧/过时文件

Inno setup Inno安装程序-更新时删除旧/过时文件,inno-setup,Inno Setup,所以,我意识到这个问题以前有人问过。事实上,在写这篇文章之前,我读了好10本书,但是没有一本书有一个适用的解决方案,我希望现在有人找到了一些东西 问题是: 我的程序是用脚本构建的,在一个文件夹中创建所有最终文件。 这些文件包含在inno中,如下所示: [Files] Source: "build\exe.win-amd64-3.6\*"; Excludes: "*.key, *.log"; DestDir: "{app}"; \ Flags: ignoreversion recurses

所以,我意识到这个问题以前有人问过。事实上,在写这篇文章之前,我读了好10本书,但是没有一本书有一个适用的解决方案,我希望现在有人找到了一些东西

问题是: 我的程序是用脚本构建的,在一个文件夹中创建所有最终文件。 这些文件包含在inno中,如下所示:

[Files]
Source: "build\exe.win-amd64-3.6\*"; Excludes: "*.key, *.log"; DestDir: "{app}"; \
    Flags: ignoreversion recursesubdirs createallsubdirs
该应用程序已经发布了几个月,并进行了不同的更新。现在已经没有旧文件的记录了,尽管它可能会经过艰苦的重新组装,因为我们有版本控制,我可以再次构建旧的安装程序

据我所知,您应该使用
InstallDelete
部分来删除旧文件-但是您不应该使用通配符,也没有
Excludes
部分来保护我们拥有的单个文件夹,其中可能包含他们可能想要保留的用户数据

那么,如何处理旧文件呢?该应用程序是100 MB,当前用户可能有300+MB的旧文件不再需要,我想清理一下


TL;DR:我希望安装程序覆盖或删除应用程序目录中的所有文件,但包含用户数据的文件夹除外。

最简单的解决方案是在安装之前删除安装文件夹中的所有文件

如你所知,你可以用它。但这不允许您排除“数据”文件夹

您可以编写Pascal脚本。看见您可以从我对“来自事件的问题”函数的回答中调用
DelTreeExceptSavesDir
函数:

过程CurStepChanged(CurStep:TSetupStep);
开始
如果CurStep=ssInstall,则
开始
DelTreeExceptSavesDir(WizardDirValue);
结束;
结束;

如果您确实希望只删除过时的文件,为了避免删除和重新创建现有文件(这不是您的情况,因为您使用的是
ignoreversion
标志),您可以使用预处理器生成要为Pascal脚本安装的文件列表,并使用该列表仅删除真正过时的文件

#pragma parseroption-p-
#定义文件项(DestDir)\
“文件未删除。添加('”+小写字母(DestDir)+');\n”
#定义进程文件(源、目标、FindResult、FindHandle)\
FindResult\
? \
本地[0]=FindGetFileName(FindHandle)\
本地[1]=源+“\\”+本地[0]\
本地[2]=Dest+“\\”+本地[0]\
(本地[0]!=”&本地[0]!=”\
?文件输入(本地[2])+\
(DirExists(Local[1])?ProcessFolder(Local[1],Local[2]):“”)\
: "") + \
进程文件(源、目标、FindNext(FindHandle)、FindHandle)\
: \
""
#定义ProcessFolder(源、目标)\
本地[0]=FindFirst(源+“\\*”,faAnyFile)\
ProcessFile(源、目标、本地[0],本地[0])
#pragma parseroption-p+
[守则]
变量
不需要删除的文件:TStringList;
函数InitializeSetup():Boolean;
开始
FilesNotToBeDeleted:=TStringList.Create;
添加('\data');
{#Trim(ProcessFolder('build\exe.win-amd64-3.6','')}
filenottobedeleted.Sorted:=True;
结果:=真;
结束;
过程DeleteObsoletFiles(路径:字符串;相对路径:字符串);
变量
FindRec:TFindRec;
FilePath:string;
FileRelativePath:字符串;
开始
如果FindFirst(路径+'\*',FindRec),则
开始
尝试
重复
如果(FindRec.Name'.'和(FindRec.Name'.'),则
开始
FilePath:=Path+'\'+FindRec.Name;
FileRelativePath:=RelativePath+'\'+FindRec.Name;
如果FindRec.Attributes和文件属性目录为0,则
开始
DeleteObsoleteFiles(FilePath,FileRelativePath);
结束;
如果filenotbedeleted.IndexOf(小写(FileRelativePath))<0,则
开始
如果FindRec.Attributes和文件属性目录为0,则
开始
如果是RemoveDir(文件路径),则
开始
日志(格式('已删除的过时目录%s',[FilePath]);
结束
其他的
开始
日志(格式('未能删除过时的目录%s',[FilePath]);
结束;
结束
其他的
开始
如果删除文件(文件路径),则
开始
日志(格式('已删除的过时文件%s',[FilePath]);
结束
其他的
开始
日志(格式('未能删除过时文件%s',[FilePath]);
结束;
结束;
结束;
结束;
直到没有FindNext(FindRec);
最后
FindClose(FindRec);
结束;
结束
其他的
开始
日志(格式('未能列出%s',[Path]);
结束;
结束;
过程CurStepChanged(CurStep:TSetupStep);
开始
如果CurStep=ssInstall,则
开始
日志('查找过时的文件…');
删除过时文件(WizardDirValue“”);
结束;
结束;


有关其他选项,请参见。

那么您想从安装文件夹中删除更新安装程序未安装的所有文件吗?是的,差不多。我在最后添加了一个摘要来澄清这一点。虽然链接的问题是关于卸载的,但答案中的代码也可以在安装程序中使用。似乎它会先删除所有内容,然后编写所有内容。如果只删除那些无论如何都不会被覆盖的内容,那就太好了。这只关系到,如果你使用了防止覆盖现有文件的标志(如果它们已经存在的话)。如果您无条件地覆盖文件,我看不出有任何区别。