在使用Inno Setup创建的安装程序的[Code]
部分的函数中,是否有可能退出安装程序?
我不想设置退出代码,我想要做的是对某个要求进行自定义检查,如果未满足该要求,则退出安装程序。
在使用Inno Setup创建的安装程序的[Code]
部分的函数中,是否有可能退出安装程序?
我不想设置退出代码,我想要做的是对某个要求进行自定义检查,如果未满足该要求,则退出安装程序。
InitializeSetup
返回False
即可。这将在向导显示之前退出安装程序。function InitializeSetup(): Boolean;
begin
Result := True;
if not PrerequisitesTest then
begin
SuppressibleMsgBox('Prerequisites test failed', mbError, MB_OK, IDOK);
Result := False;
end;
end;
如果您需要在安装开始之前测试先决条件(例如,InitializeSetup
太早),则可以从 CurStepChanged(ssInstall)
调用Abort
函数:
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;
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, IDOK);
ExitProcess(1);
end;
end;
Result := True;
end;
InitializeSetup
InitializeWizard
CurStepChanged(ssInstall)
InitializeUninstall
CurUninstallStepChanged(usAppMutexCheck)
CurUninstallStepChanged(usUninstall)
我的做法是:
procedure ExitProcess(exitCode:integer);
external 'ExitProcess@kernel32.dll stdcall';
使用它的方法是:
[Code]
if .... then begin
ExitProcess(0);
end;
/silent
)下,使用WizardForm.Close
无法工作,因此用户可以轻松绕过检查。 - Martin Prikryl这是我今天从Inno 5.6.1中摸索出来的内容,你可以在https://github.com/jrsoftware/issrc[ref1]找到相关资源。
[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文档中对于终止
的说明如下:
描述:从当前执行路径中跳出,而不报告错误。
终止引发了一个特殊的“静默异常”,其操作方式与任何其他异常相同,但不会向最终用户显示错误消息。
备注:
终止不会导致安装或卸载退出除非它在以下这些事件函数之一中被调用(或由它们调用的另一个函数):
InitializeSetup InitializeWizard CurStepChanged(ssInstall) InitializeUninstall CurUninstallStepChanged(usAppMutexCheck) CurUninstallStepChanged(usUninstall)
终止函数以这种方式工作的原因是因为,在内部Inno引发了一个EAbort
异常,并且该异常通过Delphi UI loop进行特殊处理。仅在列出的函数中,Inno开发人员已经添加了特殊处理EAbort
的功能(例如在CurStepChanged(ssInstall)
[ref2]的情况下),
-- 或该函数未通过UI loop进行调用,例如在InitializeSetup
的情况下,它是从Setup.dpr
的主程序中调用的,并且任何直接的EAbort
都会在那里通过except
块进行特殊处理。
在所有其他Inno事件函数(例如NextButtonClick
等)中,EAbort
异常将到达主程序/UI loop并在那里被忽略。
这正好引导我们到:
/SILENT
(或/VERSILENT
)时的终止()行为当Inno以静默方式运行时,它不显示向导表单UI。此时,“向导”/ Inno的进度不由UI Loop驱动,而是由与例如InitializeSetup
相同的顶级try/except
块下调用的WizardForm.ClickThroughPages
驱动的[ref3]。
Abort()
会从大多数 [Code]
函数中退出安装程序,并且在文档中给出的 Abort
列表在静默模式下运行安装程序时将无效。
CancelButtonClick(CurPageID: Integer; var Cancel, Confirm: Boolean)
(如果已定义)并终止安装程序,可能会显示一个退出窗口:
用户可以通过调用当用户单击“取消”按钮或单击窗口的“关闭”按钮时调用。
Cancel
参数指定是否应进行正常取消处理;默认为True
。Confirm
参数指定是否应显示“退出安装程序?”消息框。
WizardForm.Close()
来触发取消按钮机制,但这仅适用于 Setup 显示向导表单的情况,并且在静默模式下不起作用。
WizardForm.Close
[ref4],或者实际按钮单击,最终将调用 TMainForm.FormCloseQuery
(位于 Main.pas 中),该函数将调用 CancelButtonClick
回调[ref5],并根据 Confirm
值执行 TerminateApp();
或首先调用 helper 函数 ExitSetupMsgBox()
显示消息框给用户。
.iss .pas
和.dpr
issrc\Projects\Main.pas
:TMainForm.Install
通过SetStep(ssInstall, False);
调用,并在TMainForm.Install
的结尾处的except
块中调用TerminateApp
.Setup.dpr
从Main.pas
调用MainForm.InitializeWizard
,当not InstallMode = imNormal
即静默情况下,将调用WizardForm.ClickThroughPages
。WizardForm.Close()
内部调用MainForm.Close()
(参见:TWizardForm.FormClose
)CancelButtonClick
全局过程和每个向导页面还具有可以设置的OnCancelButtonClick:TWizardPageCancelEvent
。请查看InnoSetup帮助文档中的InitializeSetup和Abort。正如Cody所说,这是可能的。如果您遇到问题,请发布您已完成的内容以及您遇到的问题。
在你的代码段中的某处,你执行了一个检查,对吧? 作为这个检查的结果,你想要退出安装。 要执行退出,插入以下代码:
PostMessage (WizardForm.Handle, $0010, 0, 0); { quit setup, $0010=WM_CLOSE }
希望这能有所帮助
/silent
)来绕过。 - Martin Prikryl