代码之家  ›  专栏  ›  技术社区  ›  dso

当Run命令失败时,如何强制Inno安装程序失败?

  •  10
  • dso  · 技术社区  · 15 年前

    [Run]

    如何启用此功能?我找不到国旗 Run

    3 回复  |  直到 7 年前
        1
  •  10
  •   Martin Prikryl    7 年前

    [Code] 对于该部分,请使用运行文件 Exec 功能,检查 ResultCode 返回后运行卸载脚本。

        2
  •  6
  •   Martin Prikryl    7 年前

    我是这样做的:

    1. 将错误消息(中止确认消息或只是通知消息)写入临时文件 {tmp}\install.error 使用Inno安装程序的 BeforeInstall 参数与 SaveStringToUTF8File {cm:YourCustomMessage} .

    2. 使用Windows命令shell cmd.exe /s /c 运行所需的程序。也可以使用 del 指挥 && - https://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/ntcmds_shelloverview.mspx . 所以,如果命令成功,错误消息文件将被删除(退出代码0)。请注意特殊报价的处理 . 使用下面的代码作为示例。

    3. {tmp}\install.error 使用Inno安装程序的 AfterInstall 参数与 ConfirmInstallAbortOnError NotifyInstallAbortOnError 程序取决于错误严重性。他们将在适当的通知或确认(以及可选的日志文件显示)下中止安装,并使用 Exec(ExpandConstant('{uninstallexe}'), ...

    4. ShouldAbortInstallation 全局变量用于保持状态。Inno安装程序 ShouldSkipPage(PageID: Integer) 函数用于隐藏最终页面。所有命令在 [Run] 节应使用 Check 参数与 CheckInstallationIsNotAborted 作用它将阻止在某个点失败后执行它们。

    见下面的例子。希望这有帮助。

    [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;
    
        3
  •  2
  •   Martin Prikryl    4 年前

    这个 [Run] 第节发生在安装完成之后,所以此时不可能回滚,因为它已经完成。

    但是,你认为呢 可以 AfterInstall [Files] .exe 或者执行方法所需的任何内容。这将在完成安装之前运行,因此此时取消将执行回滚,以删除所有文件。

    如果你把它和 "CancelWithoutPrompt" from this answer 在交互模式下运行时 . 不幸的是 doesn't seem to be a rollback for silent mode .

    [Files]
    Source: src\myapp.exe; DestDir: "{app}"; AfterInstall: RunMyAppCheck
    
    [Code]
    var CancelWithoutPrompt: boolean;
    
    function InitializeSetup(): Boolean;
    begin
      CancelWithoutPrompt := false;
      result := true;
    end;
    
    procedure CancelButtonClick(CurPageID: Integer; var Cancel, Confirm: Boolean);
    begin
      if CancelWithoutPrompt then
        Confirm := false; { hide confirmation prompt }
    end;
    
    procedure RunMyAppCheck();
    var
      resultCode: int;
    begin
      Exec(ExpandConstant('{app}\myapp.exe'), '--verify --example-other-params',
        '', SW_HIDE, ewWaitUntilTerminated, resultCode);
      
      if resultCode <> 0 then
      begin
        SuppressibleMsgBox(
          'MyApp failed, exit code ' + IntToStr(resultCode) + '. Aborting installation.',
          mbCriticalError, MB_OK, 0);
      
        CancelWithoutPrompt := true;
        WizardForm.Close;
      end;
    end;
    
        4
  •  0
  •   Community Jaime Torres    7 年前

    你可以使用 AfterInstall 国旗 Run

    answer here .

    然后根据结果代码,您可以取消安装。