2009-07-13 8 views
10

Ho alcuni comandi nella sezione [Run] del mio script Inno Setup. Al momento, se qualcuno di essi restituisce un codice di errore (valore di ritorno diverso da zero), l'installazione continua senza alcun avviso per l'utente. Il comportamento desiderato è di avere l'installazione fallita e il rollback.Come forzare l'installazione di Inno Setup a fallire quando il comando Run fallisce?

Come abilitare? Non sono riuscito a trovare alcun flag per la voce Run che imporrà questo comportamento. Mi sto perdendo qualcosa?

+0

domanda simile: http://stackoverflow.com/questions/582452/msi-return-codes-in-inno-setup – mghie

+1

inno dovrebbe seriamente mettere in guardia per impostazione predefinita quando ciò si verifica ... Yipes – rogerdpack

+0

Vedi anche [usando il processo di uscita codice per mostrare un messaggio di errore per un file specifico in \ [Esegui \]] (http://stackoverflow.com/q/9621099/850848) e [Inno Setup: Come interrompere/terminare l'installazione durante l'installazione?] (http://stackoverflow.com/q/6345920/850848) –

risposta

9

Per quanto mi riguarda, è necessario utilizzare la sezione [Code] per quello, eseguire i file con la funzione Exec, controllare ResultCode al momento della restituzione ed eseguire lo script di disinstallazione.

+1

Per eseguire la cancellazione da [Codice], vedere questa risposta: http: // stackoverflow.com/a/12849863/382885 – PolyTekPatrick

3

ho fatto in questo modo:

  1. messaggio di Errore di scrittura (sia interrompere messaggio di conferma o messaggio di notifica solo) per file temporaneo {tmp}\install.error utilizzando il parametro di Inno Setup BeforeInstall con SaveStringToUTF8File procedura. È possibile utilizzare le costanti di Inno Setup, ad esempio {cm:YourCustomMessage}.

  2. Utilizzare la shell di comando di Windows cmd.exe /s /c per eseguire il programma desiderato. Utilizzare anche l'esecuzione condizionale del comando del con && - https://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/ntcmds_shelloverview.mspx. Quindi il file del messaggio di errore verrebbe cancellato se il comando avesse esito positivo (codice di uscita 0). Si prega di essere a conoscenza della gestione delle citazioni speciali in cmd.exe /s /c. Usa il codice qui sotto come esempio.

  3. Verificare l'esistenza di un errore file di messaggio {tmp}\install.error utilizzando il parametro di Inno Setup AfterInstall sia con ConfirmInstallAbortOnError o NotifyInstallAbortOnError procedure a seconda della gravità dell'errore. Annulleranno l'installazione con una notifica o conferma appropriata (e la presentazione facoltativa del file di registro) ed eseguiranno il rollback utilizzando Exec(ExpandConstant('{uninstallexe}'), ...

  4. ShouldAbortInstallation variabile globale utilizzata per mantenere lo stato. La funzione ShouldSkipPage(PageID: Integer) di Inno Setup viene utilizzata per nascondere la pagina finale. Tutti i comandi nella sezione [Run] devono utilizzare il parametro Check con la funzione CheckInstallationIsNotAborted. A un certo punto, impedirà la loro esecuzione dopo il fallimento.

Vedere l'esempio di seguito. Spero che questo ti aiuti.

[CustomMessages] 
InstallAbortOnErrorConfirmationMessage=An error has occurred during setup.%nAbort installation? 
InstallAbortOnErrorNotificationMessage=An error has occurred during setup.%nInstallation will be aborted. 
RunProgram1ErrorMsg=Post installation phase 1 failed. Should abort install? 
RunProgram2ErrorMsg=Post installation phase 2 failed. Installation will be aborted. Please, contact tech support. 
RunProgram1StatusMsg=Post installation phase 1 is in progress 
RunProgram2StatusMsg=Post installation phase 2 is in progress 

[Run] 
; Write error text to file. Delete file on succeed. Abort installation if file exists after command execution. 
Filename: "cmd.exe"; Parameters: "/s /c "" ""{app}\program1.exe"" /param1 /param2:""val2"" && del /F /Q ""{tmp}\install.error"" """; \ 
    WorkingDir:"{app}"; Flags: runhidden; \ 
    BeforeInstall: SaveStringToUTF8File('{tmp}\install.error', '{cm:RunProgram1ErrorMsg}', False); \ 
    AfterInstall: ConfirmInstallAbortOnError('{tmp}\install.error', '{app}\logs\setup.log'); \ 
    StatusMsg: "{cm:RunProgram1StatusMsg}"; \ 
    Check: CheckInstallationIsNotAborted; 
Filename: "cmd.exe"; Parameters: "/s /c "" ""{app}\program2.exe"" && del /F /Q ""{tmp}\install.error"" """; \ 
    WorkingDir:"{app}"; Flags: runhidden; \ 
    BeforeInstall: SaveStringToUTF8File('{tmp}\install.error', '{cm:RunProgram2ErrorMsg}', False); \ 
    AfterInstall: NotifyInstallAbortOnError('{tmp}\install.error', '{app}\logs\setup.log'); \ 
    StatusMsg: "{cm:RunProgram2StatusMsg}"; \ 
    Check: CheckInstallationIsNotAborted; 
[Code] 
var 
    ShouldAbortInstallation: Boolean; 

procedure SaveStringToUTF8File(const FileName, Content: String; const Append: Boolean); 
var 
    Text: array [1..1] of String; 
begin 
    Text[1] := Content; 
    SaveStringsToUTF8File(ExpandConstant(FileName), Text, Append); 
end; 

function LoadAndConcatStringsFromFile(const FileName: String): String; 
var 
    Strings: TArrayOfString; 
    i: Integer; 
begin 
    LoadStringsFromFile(FileName, Strings); 
    Result := ''; 
    if High(Strings) >= Low(Strings) then 
    Result := Strings[Low(Strings)]; 
    for i := Low(Strings) + 1 to High(Strings) do 
    if Length(Strings[i]) > 0 then 
     Result := Result + #13#10 + Strings[i]; 
end; 

procedure ConfirmInstallAbortOnError(ErrorMessageFile, LogFileToShow: String); 
var 
    ErrorCode: Integer; 
    ErrorMessage: String; 
begin 
    ErrorMessageFile := ExpandConstant(ErrorMessageFile); 
    LogFileToShow := ExpandConstant(LogFileToShow); 

    Log('ConfirmInstallAbortOnError is examining file: ' + ErrorMessageFile); 
    if FileExists(ErrorMessageFile) then 
    begin 
    Log('ConfirmInstallAbortOnError: error file exists'); 

    { Show log file to the user } 
    if Length(LogFileToShow) > 0 then 
     ShellExec('', LogFileToShow, '', '', SW_SHOW, ewNoWait, ErrorCode); 

    ErrorMessage := LoadAndConcatStringsFromFile(ErrorMessageFile); 
    if Length(ErrorMessage) = 0 then 
     ErrorMessage := '{cm:InstallAbortOnErrorConfirmationMessage}'; 
    if MsgBox(ExpandConstant(ErrorMessage), mbConfirmation, MB_YESNO) = IDYES then 
    begin 
     Log('ConfirmInstallAbortOnError: should abort'); 
     ShouldAbortInstallation := True; 
     WizardForm.Hide; 
     MainForm.Hide; 
     Exec(ExpandConstant('{uninstallexe}'), '/SILENT', '', SW_HIDE, 
      ewWaitUntilTerminated, ErrorCode); 
     MainForm.Close; 
    end; 
    end; 
    Log('ConfirmInstallAbortOnError finish'); 
end; 

procedure NotifyInstallAbortOnError(ErrorMessageFile, LogFileToShow: String); 
var 
    ErrorCode: Integer; 
    ErrorMessage: String; 
begin 
    ErrorMessageFile := ExpandConstant(ErrorMessageFile); 
    LogFileToShow := ExpandConstant(LogFileToShow); 

    Log('NotifyInstallAbortOnError is examining file: ' + ErrorMessageFile); 
    if FileExists(ErrorMessageFile) then 
    begin 
    Log('NotifyInstallAbortOnError: error file exists'); 

    { Show log file to the user } 
    if Length(LogFileToShow) > 0 then 
     ShellExec('', LogFileToShow, '', '', SW_SHOW, ewNoWait, ErrorCode); 

    ErrorMessage := LoadAndConcatStringsFromFile(ErrorMessageFile); 
    if Length(ErrorMessage) = 0 then 
     ErrorMessage := '{cm:InstallAbortOnErrorNotificationMessage}'; 

    MsgBox(ExpandConstant(ErrorMessage), mbError, MB_OK); 
    Log('NotifyInstallAbortOnError: should abort'); 
    ShouldAbortInstallation := True; 
    WizardForm.Hide; 
    MainForm.Hide; 
    Exec(ExpandConstant('{uninstallexe}'), '/SILENT', '', SW_HIDE, 
     ewWaitUntilTerminated, ErrorCode); 
    MainForm.Close; 
    end; 
    Log('NotifyInstallAbortOnError finish'); 
end; 

function ShouldSkipPage(PageID: Integer): Boolean; 
begin 
    Result := ShouldAbortInstallation; 
end; 

function CheckInstallationIsNotAborted(): Boolean; 
begin 
    Result := not ShouldAbortInstallation; 
end; 
+0

Anche se questo non è come è imho modo più pulito: http://stackoverflow.com/a/31427076/850848 - (+1 comunque) –

0

È possibile utilizzare il flag AfterInstall nella sezione Run per far scattare l'esecuzione del programma e prendere il codice risultato.

Vedere il mio answer here.

Quindi in base al codice del risultato è possibile annullare l'installazione.

+0

* Quindi in base al codice del risultato è possibile annullare l'installazione. * Come? – TLama

+0

Un commento ha menzionato questa risposta: http://stackoverflow.com/a/12849863/672870 Tuttavia non è un rollback. – Jason

+0

Quindi non è possibile annullare l'installazione (con rollback), vero? – TLama

Problemi correlati