13

[Code]是否可以从使用 Inno Setup 创建的安装程序部分中的功能退出安装?

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

4

6 回答 6

16

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

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

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

在此处输入图像描述


如果您只需要在安装开始之前测试先决条件(即InitializeSetup太早),您可以从以下位置调用该Abort函数CurStepChanged(ssInstall)

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

在此处输入图像描述


尽管对于这种情况,请考虑使用PrepareToInstall事件函数机制,而不是退出设置。

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

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

在此处输入图像描述


如果您需要在其他任何时候强制终止安装程序,请使用ExitProcessWinAPI 调用:

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, IDOK);
      ExitProcess(1);
    end;
  end;
  Result := True;
end;

虽然这是相当不安全的出口,但仅将其用作最后的手段。如果您加载了任何外部 DLL,您可能需要先将其卸载,以避免崩溃。这也不会清理临时目录。

在此处输入图像描述


于 2016-09-30T10:08:23.003 回答
14

如果您在这些事件中,您可以使用Abort() :

InitializeSetup
InitializeWizard
CurStepChanged(ssInstall)
InitializeUninstall
CurUninstallStepChanged(usAppMutexCheck)
CurUninstallStepChanged(usUninstall)
于 2011-08-11T08:17:25.700 回答
10

我这样做的方式是:

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

并且使用方法是:

[Code]
  if .... then begin
     ExitProcess(0);
  end;
于 2011-08-11T07:32:22.913 回答
4

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

于 2010-12-14T12:21:28.480 回答
4

这是我今天从 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 设置退出/取消和中止的剖析

Abort

状态的 Inno 文档Abort

说明:从当前执行路径逃逸而不报错。

Abort 会引发一个特殊的“静默异常”,它的运行方式与任何其他异常一样,但不会向最终用户显示错误消息。

备注:
Abort不会导致 Setup 或 Uninstall 退出,除非这些事件函数之一(或它们调用的另一个函数)调用它:

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

Abort() 行为解释

Abort 函数以这种方式出现的原因是,在内部,Inno 引发了EAbort异常,并且Delphi UI 循环对异常进行了特殊处理在列出的功能中,Inno 开发人员添加了特殊处理EAbort(如CurStepChanged(ssInstall)[ref2]的情况),-

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

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

这很好地引导我们:

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

当 Inno 静默运行时,它不会显示向导表单 UI。然后,“向导”/ Inno 的进度不是由 UI 循环驱动,而是由 驱动,它在与eg 相同的顶层块WizardForm.ClickThroughPages下被调用。[参考文献3]try/exceptInitializeSetup

因此,如果 Inno 被静默调用,Abort() 将从每个大多数[Code]函数中退出 setup,如果 setup 静默运行,文档中给出的列表将Abort变得毫无意义。

取消

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

在这种情况下,Inno 将调用回调函数CancelButtonClick(CurPageID: Integer; var Cancel, Confirm: Boolean)(如果已定义)并终止设置,可能会出现一个逃生舱口对话框:

当用户单击取消按钮或单击窗口的关闭按钮时调用。该Cancel参数指定是否应该进行正常的取消处理;它默认为True. 该Confirm参数指定是否有“退出安装程序?” 应显示消息框;

用户[Code]可以通过调用来调用取消按钮机制WizardForm.Close(),但这仅在安装程序显示向导表单时有效,并且在静默模式下不起作用

取消详情

WizardForm.Close[ref4]或单击实际按钮最终将调用TMainForm.FormCloseQuery(在 Main.pas 中),它将调用CancelButtonClick回调[ref5]并取决于Confirm值,直接调用或首先调用将显示消息框TerminateApp();的辅助函数ExitSetupMsgBox()用户。



脚注:

  • [ref1]:对于非 delphi 人员:如果您在文本编辑器中搜索源代码,请确保至少包含.iss .pas .dpr
  • [ref2] : ssInstall 异常处理位于issrc\Projects\Main.pas: TMainForm.InstallviaSetStep(ssInstall, False);和whereexcept末尾的块被调用。TMainForm.InstallTerminateApp
  • [ref3] : 参见Setup.dprcall MainForm.InitializeWizardfrom Main.paswhich calls WizardForm.ClickThroughPagesiff not InstallMode = imNormal,即在静默情况下。
  • [ref4]:WizardForm.Close()内部调用MainForm.Close()(见TWizardForm.FormClose:)
  • [ref5] : Inno 中实际上有两种可定义的取消按钮点击回调[Code]:全局CancelButtonClick过程,每个向导页面也有一个OnCancelButtonClick: TWizardPageCancelEvent可以设置的。
于 2019-05-07T10:30:56.700 回答
1

在您的代码部分的某处执行检查。正确的?作为该检查的结果,您要退出安装。要执行退出,请输入以下行:

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

希望这会有所帮助

于 2011-01-21T22:50:27.017 回答