2009-07-13 129 views
10

我在Inno Setup脚本的[Run]部分有一些命令。现在,如果其中任何一个返回了失败代码(非零返回值),则安装程序继续而不会对用户发出任何警告。所需的行为是让安装程序失败并回滚。运行命令失败时如何强制Inno Setup安装失败?

如何启用此功能?我找不到Run条目的任何标志,这会强制执行此行为。我错过了什么吗?

+0

相似问题:http://stackoverflow.com/questions/582452/msi-return-codes-in-inno-setup – mghie 2009-07-15 20:26:04

+1

当这种情况发生时,inno应该严肃地警告...... yipes – rogerdpack 2011-09-15 23:09:33

+0

另请参见[使用Process Exit代码以显示\ [Run \]](http://stackoverflow.com/q/9621099/850848)中的特定文件的错误消息和[Inno Setup:如何在安装过程中中止/终止安装?](http:/ /stackoverflow.com/q/6345920/850848) – 2017-05-11 13:11:11

回答

9

就我而言,您必须使用[Code]部分,运行Exec函数的文件,返回时检查ResultCode并运行卸载脚本。

+1

要从[Code]执行取消操作,请参阅此答案:http:// stackoverflow。com/a/12849863/382885 – PolyTekPatrick 2015-05-13 21:50:12

3

我就是这么做的:

  1. 写入错误消息(要么放弃确认消息,或只是通知消息)到临时文件{tmp}\install.error使用创新安装的BeforeInstall参数与SaveStringToUTF8File程序。您可以使用Inno Setup的常量,例如{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),错误消息文件将被删除。请注意0​​中的特殊报价处理。以下面的代码为例。

  3. 检查错误消息文件{tmp}\install.error存在使用创新安装的AfterInstall参数与依赖于错误的严重性,无论是ConfirmInstallAbortOnErrorNotifyInstallAbortOnError程序。他们将通过适当的通知或确认(以及可选的日志文件呈现)中止安装并执行回滚。使用全局变量保持状态。全局变量用于保持状态。 Inno Setup的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; 
0

可以使用AfterInstall国旗在Run部分触发程序的执行,赶上结果代码。

请参阅我的answer here

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