2009-07-13 173 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

然後根據結果代碼您可以取消安裝。