如何告诉InnoSetup不要卸载(文本)由用户更改的文件(==与InnoSetup安装的文件不同)?或者更难:当在现有的版本上安装新版本时,InnoSetup应该询问用户是否覆盖已更改的文件,但是在纯卸载时,它应该在不询问的情况下卸载它。InnoSetup:不要卸载已更改的文件
回答
我最近有一个类似的问题。这是我的解决方案,用于检测文本文件(配置文件)是否已从上次安装运行期间安装的文本文件(配置文件)更改为:
使用ISPP(Inno Setup Pre-Processor)创建文本文件及其哈希列表编译时间:
[Files]
; ...
#define FindHandle
#define FindResult
#define Mask "Profiles\*.ini"
#sub ProcessFoundFile
#define FileName "Profiles\" + FindGetFileName(FindHandle)
#define FileMd5 GetMd5OfFile(FileName)
Source: {#FileName}; DestDir: {app}\Profiles; Components: profiles; \
Check: ProfileCheck('{#FileMd5}'); AfterInstall: ProfileAfterInstall('{#FileMd5}');
#endsub
#for {FindHandle = FindResult = FindFirst(Mask, 0); FindResult; FindResult = FindNext(FindHandle)} ProcessFoundFile
在“代码”部分顶部我定义了一些有用的东西:
[Code]
var
PreviousDataCache : tStringList;
function InitializeSetup() : boolean;
begin
// Initialize global variable
PreviousDataCache := tStringList.Create();
result := TRUE;
end;
function BoolToStr(Value : boolean) : string;
begin
if (not Value) then
result := 'false'
else
result := 'true';
end;
在“检查”事件处理程序我比较以前的散列安装和当前文件:
function ProfileCheck(FileMd5 : string) : boolean;
var
TargetFileName, TargetFileMd5, PreviousFileMd5 : string;
r : integer;
begin
result := FALSE;
TargetFileName := ExpandConstant(CurrentFileName());
Log('Running check procedure for file: ' + TargetFileName);
if not FileExists(TargetFileName) then
begin
Log('Check result: Target file does not exist yet.');
result := TRUE;
exit;
end;
try
TargetFileMd5 := GetMd5OfFile(TargetFileName);
except
TargetFileMd5 := '(error)';
end;
if (CompareText(TargetFileMd5, FileMd5) = 0) then
begin
Log('Check result: Target matches file from setup.');
result := TRUE;
exit;
end;
PreviousFileMd5 := GetPreviousData(ExtractFileName(TargetFileName), '');
if (PreviousFileMd5 = '') then
begin
r := MsgBox(TargetFileName + #10#10 +
'The existing file is different from the one Setup is trying to install. ' +
'It is recommended that you keep the existing file.' + #10#10 +
'Do you want to keep the existing file?', mbConfirmation, MB_YESNO);
result := (r = idNo);
Log('Check result: ' + BoolToStr(result));
end
else if (CompareText(PreviousFileMd5, TargetFileMd5) <> 0) then
begin
r := MsgBox(TargetFileName + #10#10 +
'The existing file has been modified since the last run of Setup. ' +
'It is recommended that you keep the existing file.' + #10#10 +
'Do you want to keep the existing file?', mbConfirmation, MB_YESNO);
result := (r = idNo);
Log('Check result: ' + BoolToStr(result));
end
else
begin
Log('Check result: Existing target has no local modifications.');
result := TRUE;
end;
end;
在“AfterInstall”事件处理程序中,我将文件哈希标记为稍后存储在 注册表中。因为在我的测试中,如果文件移动失败的事件被触发甚至(目标文件是只读的),我又比较散,以找出是否将文件移动成功:
procedure ProfileAfterInstall(FileMd5 : string);
var
TargetFileName, TargetFileMd5 : string;
begin
TargetFileName := ExpandConstant(CurrentFileName());
try
TargetFileMd5 := GetMd5OfFile(TargetFileName);
except
TargetFileMd5 := '(error)';
end;
if (CompareText(TargetFileMd5, FileMd5) = 0) then
begin
Log('Storing hash of installed file: ' + TargetFileName);
PreviousDataCache.Add(ExtractFileName(TargetFileName) + '=' + FileMd5);
end;
end;
procedure RegisterPreviousData(PreviousDataKey : integer);
var
Name, Value : string;
i, n : integer;
begin
for i := 0 to PreviousDataCache.Count-1 do
begin
Value := PreviousDataCache.Strings[i];
n := Pos('=', Value);
if (n > 0) then
begin
Name := Copy(Value, 1, n-1);
Value := Copy(Value, n+1, MaxInt);
SetPreviousData(PreviousDataKey, Name, Value);
end;
end;
end;
我可以问你什么时候调用RegisterPreviousData()? –
@JulienM:如果存在具有该名称的函数,则“RegisterPreviousData”是由Inno Setup自动调用的事件函数。有关更多信息,请参阅Inno Setup帮助。 – blerontin
良好的工作;如果一个相当于这个的标志可以被添加到InnoSetup中会更好! –
Inno无法在本地执行此检查。
要在安装过程中不替换已更改的文件,您需要使用自定义[Code]
来执行校验和,并与预先计算或从以前的安装中保存的已知良好值进行比较。
为避免在卸载过程中将其删除,您需要先禁用Inno自己的卸载,然后在删除它们之前检查相同的校验和,再次在[Code]
。
请注意,最好保留用户可以在设置之外编辑的任何文件,以更好地处理这种情况并正确遵守应用程序指南。
- 1. 更改文件的文本,而不会破坏卸载过程
- 2. 不要使用WSPBuilder卸载文件
- 3. 如何强制InnoSetup创建卸载日志文件
- 4. 在InnoSetup中添加卸载图标
- 5. InnoSetup卸载提问信息 - Pascal编码
- 6. 只下载已更改的文件git
- 7. InnoSetup:“文件的卷已被外部改变”
- 8. 更改页面后卸载事件
- 9. InstallShield2010 XML文件修改和卸载更改
- 10. MSI不卸载.dll文件
- 11. 将Git中的更改卸载到特定文件中
- 12. 备份文件并使用InnoSetup进行卸载时恢复它们?
- 13. Tabcontrol - 选择更改加载/卸载
- 14. RUnit测试已卸载的软件包
- 15. 拆卸,更改和组装DLL文件
- 16. Relay-Modern试图更新已经卸载的组件`Relay(Songs)`
- 17. Git - 查看已更改的文件,即使已删除更改
- 18. InnoSetup如何确定卸载程序窗口的HWND?
- 19. 文件位置已更改?
- 20. 卸载Cornerstone中的文件
- 21. 如何在InnoSetup中更改安装目标文件夹权限?
- 22. 如何更改InnoSetup中的下载路径?
- 23. 如何更改InnoSetup页面的顺序?
- 24. 在卸载时删除已安装文件的推荐库/宏
- 25. InstallShield:在卸载时删除已安装的文件
- 26. 卸载Git中所有已删除的文件
- 27. 卸载已使用CUDA内存的mex文件时,MATLAB崩溃
- 28. 使用Inno Setup卸载已创建的日志文件
- 29. bat文件来卸载已安装的应用程序
- 30. InnoSetup中的文件选择
也许你可以使用'UninsNeverUninstall'标志,然后为'CurUninstallStepChanged'' usPostUninstall'添加一个'[CODE]'部分,其中所有的TXT文件将检查CRC,然后删除,如果CRC相等或者CRC不等于用户将被通知有关更改的文件+询问文件是否应该删除。 – RobeN
这些文件是什么?如果是配置文件,最好使用不同的名称安装默认文件,然后将其复制到主配置文件中不存在的位置。如果它们是用户文件,则安装程序根本不应触摸它们。 – Deanna