Cómo forzar instalación Inno Setup a fallar cuando el comando Ejecutar falla?

StackOverflow https://stackoverflow.com/questions/1122588

  •  13-09-2019
  •  | 
  •  

Pregunta

Tengo algunos comandos en la sección [Run] de mi guión Inno Setup. En este momento, si alguno de ellos devuelve un código de error (valor de retorno distinto de cero), la configuración continúa sin ninguna advertencia al usuario. El comportamiento deseado es tener la configuración fallar y deshacer.

¿Cómo activo esto? No pude encontrar ninguna bandera para la entrada Run que obligaría a este comportamiento. Me estoy perdiendo algo?

¿Fue útil?

Solución

En lo que a mí respecta, usted tiene que utilizar la sección [Code] para ello, ejecute los archivos con la función Exec, comprobar ResultCode a su regreso y ejecutar el script de desinstalación.

Otros consejos

Lo hice de esta manera:

  1. mensaje de error de escritura (ya sea abortar mensaje de confirmación o simplemente mensaje de notificación) a {tmp}\install.error archivo temporal con el parámetro BeforeInstall de Inno Setup con el procedimiento SaveStringToUTF8File. Puede utilizar las constantes de Inno Setup, como {cm:YourCustomMessage}.

  2. El uso de Windows cmd.exe /s /c shell de comandos para ejecutar el programa deseado. También utilice la ejecución condicional de mando del con && - https://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/ntcmds_shelloverview.mspx . Así archivo de mensajes de error se eliminaría si el comando tiene éxito (código de salida 0). Tenga en cuenta las cotizaciones especiales de manipulación en cmd.exe /s /c. Utilice el código a continuación como ejemplo.

  3. Comprobar la existencia del mensaje de error {tmp}\install.error archivo mediante el parámetro AfterInstall de Inno Setup con procedimientos bien ConfirmInstallAbortOnError o NotifyInstallAbortOnError dependiendo de la severidad de error. Ellos abortar la instalación con la debida notificación o confirmación (y la presentación opcional del archivo de registro) y realizar la recuperación utilizando Exec(ExpandConstant('{uninstallexe}'), ...

  4. ShouldAbortInstallation variable global se utiliza para mantener el estado. ShouldSkipPage(PageID: Integer) función de Inno Setup se utiliza para ocultar la página final. Todos los comandos en la sección [Run] deben utilizar el parámetro Check con la función CheckInstallationIsNotAborted. Se evitará su ejecución después de un fallo en algún momento.

Consulte el siguiente ejemplo. Espero que esto ayude.

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

Puede usar la bandera AfterInstall en la sección Run para desencadenar la ejecución de su programa y coger el código de resultado.

.

A continuación, de acuerdo con el código de resultado se puede cancelar la instalación.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top