2012-05-21 61 views
9

¿Cómo decirle a InnoSetup que no desinstale (el texto) los archivos que el usuario ha modificado (== son diferentes de los instalados por InnoSetup)?InnoSetup: no desinstale los archivos modificados

O tal vez más difícil: al instalar una nueva versión sobre una existente, InnoSetup debe preguntar al usuario si sobrescribir el archivo modificado, pero en una desinstalación pura, debe desinstalarlo sin preguntar.

+0

tal vez usted podría usar 'UninsNeverUninstall' marcar y luego agregar una sección '[CODE]' para 'CurUninstallStepChanged'' usPostUninstall' donde todos los archivos TXT verifiquen CRC y luego se eliminen si CRC es igual o si CRC no es igual a los usuarios se les informará sobre los archivos cambiados + se preguntará si los archivos deben borrado – RobeN

+1

¿Cuáles son los archivos? Si es un archivo de configuración, es mejor instalar un archivo predeterminado con un nombre diferente y luego copiarlo en el lugar del archivo de configuración principal, si no existe. Si son archivos de usuario, la configuración no debería tocarlos en absoluto. – Deanna

Respuesta

6

Recientemente tuve un problema similar. Esta fue mi solución para detectar si un archivo de texto (perfil) ha sido cambiado desde el instalado durante la última instalación ejecutada:

Use ISPP (Preprocesador de configuración Inno) para crear la lista de archivos de texto y sus valores hash en tiempo de compilación:

[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 

En la parte superior de la sección "Código" defino algunas cosas útiles:

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

En el controlador de eventos "Check" comparo los hashes de instalación anterior y el archivo actual:

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; 

En el controlador de eventos "AfterInstall" marque el hash del archivo que se almacenará en Registro más tarde. Debido a que en mis pruebas el evento se activó incluso si el archivo Error mover (archivo de destino es de sólo lectura) comparo el hash de nuevo para averiguar si el archivo de movimiento fue exitosa:

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

¿Puedo preguntar cuando llamas a RegisterPreviousData()? –

+2

@JulienM: 'RegisterPreviousData' es una función de evento llamada por Inno Setup automáticamente si existe una función con ese nombre. Consulte la Ayuda de Inno Setup para obtener más información. – blerontin

+0

Buen trabajo; Sería bueno si una bandera equivalente a esto se pudiera agregar a InnoSetup. –

1

Inno no se puede hacer esta comprobación de forma nativa.

Para no reemplazar los archivos cambiados durante la instalación, deberá usar el [Code] personalizado para hacer una suma de comprobación y comparar con un valor bueno conocido precalculado o guardado de la instalación anterior.

Para evitar eliminarlos durante la desinstalación, deberá deshabilitar la propia desinstalación de Inno para ese archivo y consultar la misma suma de comprobación antes de eliminarlos, nuevamente en [Code].

Tenga en cuenta que es mejor mantener los archivos que el usuario puede editar fuera de la configuración para manejar mejor esta situación y cumplir correctamente con las pautas de la aplicación.

Cuestiones relacionadas