从[code]退出Inno安装程序安装

时间:2010-12-14 11:09:41

标签: inno-setup

是否可以从使用inno setup创建的安装程序的[code]部分中的函数退出安装?

我对设置退出代码不感兴趣,我想要做的是对需求执行自定义检查,如果先前没有安装该需求,则退出安装。

6 个答案:

答案 0 :(得分:10)

如果您参加这些活动,可以使用中止()

InitializeSetup
InitializeWizard
CurStepChanged(ssInstall)
InitializeUninstall
CurUninstallStepChanged(usAppMutexCheck)
CurUninstallStepChanged(usUninstall)

答案 1 :(得分:8)

我这样做的方式是:

procedure ExitProcess(exitCode:integer);
  external 'ExitProcess@kernel32.dll stdcall';

使用它的方式是:

[Code]
  if .... then begin
     ExitProcess(0);
  end;

答案 2 :(得分:7)

为了防止安装程序运行,当先决条件测试失败时,只需从InitializeSetup返回False。这将在向导显示之前退出安装程序。

function InitializeSetup(): Boolean;
begin
  Result := True;

  if not PrerequisitesTest then
  begin                     
    SuppressibleMsgBox('Prerequisites test failed', mbError, MB_OK, MB_OK);
    Result := False;
  end;
end;

enter image description here

如果您只需要在安装开始之前测试先决条件(即InitializeSetup太早),您可以从Abort function致电CurStepChanged(ssInstall)

procedure CurStepChanged(CurStep: TSetupStep);
begin
  if CurStep = ssInstall then
  begin
    if not PrerequisitesTest then
    begin                     
      SuppressibleMsgBox('Prerequisites test failed', mbError, MB_OK, MB_OK);
      Abort;
    end;
  end;
end;

enter image description here

虽然对于这种情况,请考虑使用PrepareToInstall event function机制,而不是退出设置。

function PrepareToInstall(var NeedsRestart: Boolean): String;
begin
  Result := '';

  if not PrerequisitesTest then
  begin                     
    Result := 'Prerequisites test failed';
  end;
end;

enter image description here

如果您需要在任何时候强制终止安装程序,请使用ExitProcess WinAPI电话:

procedure ExitProcess(uExitCode: Integer);
  external 'ExitProcess@kernel32.dll stdcall';

function NextButtonClick(CurPageID: Integer): Boolean;
begin
  if CurPageID = wpReady then
  begin
    if not PrerequisitesTest then
    begin                     
      SuppressibleMsgBox('Prerequisites test failed', mbError, MB_OK, MB_OK);
      ExitProcess(1);
    end;
  end;
  Result := True;
end;

虽然这是相当不安全的退出,但只能将它作为最后的手段。

enter image description here

答案 3 :(得分:3)

在InnoSetup帮助中查看InitializeSetup和Abort。正如科迪所说,这是可能的。如果您遇到问题,请发布您已完成的工作以及您遇到的问题。

答案 4 :(得分:0)

在代码部分的某个位置执行检查。对? 作为该检查的结果,您想要退出安装。 要执行退出,请输入以下行:

PostMessage (WizardForm.Handle, $0010, 0, 0);  { quit setup, $0010=WM_CLOSE }

希望这会有所帮助

答案 5 :(得分:0)

这是我今天从Inno 5.6.1中整理出来的内容以及您可以在https://github.com/jrsoftware/issrc上找到的源的写照。 [ref1]

“从[代码]退出”的一种可能有用的全面解决方案

TL; DR示例:

[Code]
var _ImmediateInnoExit_was_invoked_flag: Boolean; // Inno/Pascal Script initializes all Boolean to False.

procedure ImmediateInnoExit();
  var MainFormRef: TForm;
begin
  _ImmediateInnoExit_was_invoked_flag := True;
  try
    MainFormRef := MainForm(); // calls GetMainForm() in Inno pascal code, which will raise an internal exception if the form is not yet initialized.
    Log('INFO: ImmediateInnoExit: Calling MainForm.Close()!');
    Log('NOTE: If the Event Fn CancelButtonClick is not coded to auto-Confirm, this will display the cancel dialog in the GUI case!');
    Log('NOTE: Code will stall inside the Close() function while the Cancel confirmation dialog is displayed.');
    MainFormRef.Close(); // this is only effective if the Wizard is visible, but we cann call it even when running siently (as long as the Wizard is initialized)
    Log('NOTE: MainForm.Close() invoked. (If confirmed, setup will exit.)');
  except
    Log('INFO: ImmediateInnoExit did not resolve MainForm -> assuming we were call in an InitializeSetup() context before the Main form has been created!');
  end;

  Log('INFO: ImmediateInnoExit: Calling Abort() -> EAbort!');
  Log('NOTE: Will exit the current scope.');
  Log('NOTE:   In GUI mode, it will just jump up to the Delphi event loop (and be ignored there). (But the WizardForm.Close() call should lead to exit!)');
  Log('NOTE:   In Silent Mode, it will be caught and exit the setup.');
  Abort(); // Raise EAbort
end;

// This is called when the user clicks the cancel button or the [x] Close button
// the close/cancel can be invoked from code via WizardForm.Close!
procedure CancelButtonClick(CurPageID: Integer; var Cancel, Confirm: Boolean);
begin

  Log(Format('IN: CancelButtonClick(%d <- Cancel=[%d], Confirm=[%d])', [CurPageID, Cancel, Confirm]));
  Confirm := not _ImmediateInnoExit_was_invoked_flag; // if Confirm==False we don't get the dialog prompt.
  Log(Format('IN: CancelButtonClick(%d -> [%d], [%d])', [CurPageID, Cancel, Confirm]));
end;

现在到上面代码的重点是:

Inno Setup退出/取消和中止的剖析

Abort

Abort的Inno文档:

  

说明:   从当前执行路径中退出,而不会报告错误。

     

Abort引发了一个特殊的“无声异常”,其运行方式与任何   其他异常,但不会在最后显示错误消息   用户。

     

备注:
  中止不会导致安装程序或卸载退出除非,这称为   来自事件功能之一(或由   他们):

     

InitializeSetup InitializeWizard CurStepChanged(ssInstall) InitializeUninstall CurUninstallStepChanged(usAppMutexCheck) CurUninstallStepChanged(usUninstall)

解释Abort()行为

Abort函数以这种方式出现的原因是因为Inno在内部引发了EAbort异常,而该异常是treated specially by the Delphi UI loop在列出的功能中,Inno开发人员已为EAbort添加了特殊待遇(例如CurStepChanged(ssInstall) [ref2] ), -

-或未通过UI循环调用的函数os,例如InitializeSetup,它是从Setup.dpr的主程序中调用的,任何直接的EAbort都是在那里的except块专门处理了。

在所有其他Inno事件函数(例如NextButtonClick等)中,EAbort异常将到达主程序/ UI循环,并在那里被忽略。

这很好地引导我们去做:

运行/SILENT(或/VERSILENT)时的Abort()行为

当Inno静默运行时,它不会显示向导表单UI。然后,“向导” / Inno的进度不是不是由UI循环驱动,而是由WizardForm.ClickThroughPages驱动,try/except在与顶层InitializeSetup相同的顶级块下调用。 Abort()。 [ref3]

因此,如果以静默方式调用Inno,[Code] 将从每个大多数Abort函数的退出设置,如果安装程序正在静默运行,则[Cancel]文档中的内容将变得毫无意义。

取消

要取消设置,用户可以单击设置向导的[X]按钮或Cancel关闭按钮。

在这种情况下,Inno将调用回调函数CancelButtonClick(CurPageID: Integer; var Cancel, Confirm: Boolean)(如果已定义)并终止设置,可能会使用转义阴影对话框:

  

当用户单击“取消”按钮或单击窗口的   关闭按钮。 True参数指定是否正常取消   应进行处理;它默认为Confirm[Code]参数   指定是否“退出设置”?消息框应显示;

用户 WizardForm.Close()可以通过调用WizardForm.Close来调用取消按钮机制,但这仅在安装程序正在显示向导表单且不起作用的情况下有效处于静音模式

取消详细信息

TMainForm.FormCloseQuery [ref4] 或单击实际按钮,最终将调用CancelButtonClick(在Main.pas中),后者将调用Confirm callbacks [ref5] 并取决于TerminateApp();的值,直接调用ExitSetupMsgBox()或先调用帮助程序功能.iss .pas,该功能将向用户显示消息框。



脚注:

  • [ref1]:对于非delphi人士:如果您在文本编辑器中搜索源,请确保至少包括.dpr TMainForm.Install
  • [ref2]:ssInstall异常处理位于issrc\Projects\Main.pasSetStep(ssInstall, False);,通过exceptTMainForm.Install块位于TerminateApp的末尾,其中{{ 1}}被调用。
  • [ref3]:请参见Setup.dprMainForm.InitializeWizard调用Main.pasWizardForm.ClickThroughPages,如果not InstallMode = imNormal调用WizardForm.Close(),即在静默情况下。
  • [ref4]:MainForm.Close()内部调用TWizardForm.FormClose(请参阅:[Code]
  • [ref5]:实际上,在Inno CancelButtonClick中可定义两种取消按钮单击回调:全局OnCancelButtonClick: TWizardPageCancelEvent过程,每个向导页面还具有一个<form> <label class="checkbox-inline"> <input type="checkbox" value="1" name="state">State </label> <label class="checkbox-inline"> <input type="checkbox" value="2" name="district">District </label> <label class="checkbox-inline"> <input type="checkbox" value="3" name="Police_station">Police Station </label> 设置。