Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>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:</p> <p>Use ISPP (Inno Setup Pre-Processor) to create the list of text files and their hashes at compile time:</p> <pre><code>[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></pre> <p>At the top of the "Code" section I define some useful things:</p> <pre><code>[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; </code></pre> <p>In the "Check" event handler I compare the hashes of previous install and current file:</p> <pre><code>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) &lt;&gt; 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; </code></pre> <p>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:</p> <pre><code>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 &gt; 0 ) then begin Name := Copy(Value, 1, n-1); Value := Copy(Value, n+1, MaxInt); SetPreviousData(PreviousDataKey, Name, Value); end; end; end; </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload