InnoSetup:不要卸载更改的文件 [英] InnoSetup: don't uninstall changed files
问题描述
如何告诉InnoSetup不要卸载用户更改过的(文本)文件(==与InnoSetup安装的文件不同)?
How to tell InnoSetup to not uninstall (text) files which had been changed by the user (== are different from those installed by InnoSetup)?
也许更困难:在现有系统上安装新版本时,InnoSetup应该询问用户是否覆盖更改的文件,但是在纯卸载时,它应该不询问而将其卸载.
Or maybe more difficult: when installing a new version over an existing, InnoSetup should ask the user whether to overwrite the changed file, but on a pure uninstall, it should uninstall it without asking.
推荐答案
我最近遇到了类似的问题.这是我的解决方案,用于检测文本文件(配置文件)是否已从上次安装运行期间安装的文本文件(配置文件)进行了更改:
I recently had a similar problem. This was my solution to detect if a text file (profile) has been changed from the one installed during the last installation run:
使用ISPP(Inno Setup预处理程序)在编译时创建文本文件及其哈希的列表:
Use ISPP (Inno Setup Pre-Processor) to create the list of text files and their hashes at compile time:
[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
在代码"部分的顶部,我定义了一些有用的东西:
At the top of the "Code" section I define some useful things:
[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;
在检查"事件处理程序中,我比较了先前安装和当前文件的哈希值:
In the "Check" event handler I compare the hashes of previous install and current file:
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"事件处理程序中,我将文件哈希标记为要存储在其中 稍后注册.因为在我的测试中,即使文件移动失败(目标文件为只读)也触发了该事件,所以我再次比较散列以找出文件移动是否成功:
In the "AfterInstall" event handler I mark the file hash to be stored in Registry later. Because in my tests the event was triggered even if the file move failed (target file is read-only) I compare the hash again to find out if the file move was successful:
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;
这篇关于InnoSetup:不要卸载更改的文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!