2012-05-21 5 views
9

Как сообщить InnoSetup не удалять (текстовые) файлы, которые были изменены пользователем (== отличаются от установленных InnoSetup)?InnoSetup: не удалять измененные файлы

Или, может быть, сложнее: при установке новой версии поверх существующей InnoSetup должен попросить пользователя перезаписать измененный файл, но при чистом удалении он должен удалить его, не спрашивая.

+0

Может быть, вы могли бы использовать 'UninsNeverUninstall' флаг, а затем добавьте раздел '[CODE]' для 'CurUninstallStepChanged'' usPostUninstall', где все файлы TXT будут проверяться на CRC, а затем удалены, если CRC будет равен или CRC не равно пользователю будет проинформирован об измененных файлах + спросил, должны ли файлы быть удален. – RobeN

+1

Какие файлы? Если файл конфигурации, лучше установить файл по умолчанию с другим именем, а затем скопировать его на место основного файла конфигурации, если он не существует. Если это пользовательские файлы, настройка не должна касаться их вообще. – Deanna

ответ

6

У меня недавно была аналогичная проблема. Это было моим решением для обнаружения, если текстовый файл (профиль) был изменен с того, который был установлен во время последнего запуска установки:

Используйте ISPP (предварительный процессор настройки Inno), чтобы создать список текстовых файлов и их хэшей в время компиляции:

[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; 
+0

Могу ли я спросить, когда вы вызываете RegisterPreviousData()? –

+2

@JulienM: 'RegisterPreviousData' - это функция события, вызываемая Inno Setup автоматически, если существует функция с таким именем. Дополнительную информацию см. В справке по установке Inno. – blerontin

+0

Хорошая работа; было бы неплохо, если бы флаг, эквивалентный этому, мог быть добавлен в InnoSetup! –

1

Inno не может выполнить эту проверку изначально.

Чтобы не заменять измененные файлы во время установки, вам необходимо использовать пользовательский [Code] для выполнения контрольной суммы и сравнить с известным хорошим значением, которое предварительно вычислено или сохранено из предыдущей установки.

Чтобы избежать их удаления во время удаления, вам необходимо отключить собственную деинсталляцию Inno для этого файла и проверить ее с той же контрольной суммой, прежде чем удалять их, снова в [Code].

Обратите внимание, что лучше сохранить файлы, которые пользователь может редактировать вне установки, чтобы лучше справляться с этой ситуацией и правильно придерживаться руководящих принципов приложения.

Смежные вопросы