仅将 Inno Setup UI 用作自解压程序 - 无需安装

Use Inno Setup UI as a self-extractor only - No installation

我为许多 "standard" 安装程序使用 Inno Setup,但是对于这个任务我需要提取一堆临时文件,运行 其中一个,然后删除它们并退出安装程序(没有实际上安装任何东西)。

基本上,我希望制作一个自解压器,而不是 "installer",并希望使用 inno setup 获得最佳用户体验。

我有以下代码,几乎可以正常工作:

[Files]
Source: "dist\*"; Flags: recursesubdirs ignoreversion dontcopy;
[Code]
function InitializeSetup(): Boolean;
var
  ResultCode: Integer;
begin
  Result := True;
  MsgBox('Please wait a minute or two...', mbInformation, MB_OK);
  ExtractTemporaryFiles('{tmp}\*');
  Exec(ExpandConstant('{tmp}\MyScript.exe'), '', '', SW_HIDE, ewWaitUntilTerminated, ResultCode);
  Abort();
end;

问题是,我在这里能做的最好的事情就是显示一个消息框 "Please wait a minute or two...",用户单击 [确定],然后等待,因为屏幕上什么也没有,似乎什么也没有发生,然后 MyScript.exe开始。

我想要的是一个向导页面,上面写着 "Please wait as temporary files are extracted..." 和 npbstMarquee 风格的进度条,然后在文件被提取和我的脚本启动后消失。

我不认为有什么方法可以让 Inno Setup 在 ExtractTemporaryFiles() 进行时显示进度条(这将是理想的)并且将其用于自定义向导页面让我感到困惑。

似乎 ExtractTemporaryFiles() 实质上锁定了 UI 直到它完成,因此无法在此处设置进度条(或选取框)动画。

在执行 ExtractTemporaryFiles() 时在屏幕上显示消息也很困难。我是这样解决的:

const
  WM_SYSCOMMAND = 274;
  SC_MINIMIZE = $F020;
//-------------------------------------------------------------------
procedure MinimizeButtonClick();
begin
  PostMessage(WizardForm.Handle, WM_SYSCOMMAND, SC_MINIMIZE, 0);
end;
//-------------------------------------------------------------------
procedure CurPageChanged(CurPageID: Integer);
var
  ResultCode: Integer;
begin
  if CurPageID = wpPreparing then
  begin
    MinimizeButtonClick();
    Exec(ExpandConstant('{tmp}\MyScript.exe'), '', '', SW_HIDE, ewWaitUntilTerminated, ResultCode);
  end;
end;
//-------------------------------------------------------------------
function NextButtonClick(CurPageID: Integer): Boolean;
var
  ProgressPage: TOutputProgressWizardPage;
begin
  if CurPageID = wpReady then
  begin
    ProgressPage := CreateOutputProgressPage('Preparing files...', '');
    ProgressPage.Show;
    try
      ProgressPage.Msg1Label.Caption := 'This process can take several minutes; please wait ...';
      ExtractTemporaryFiles('{tmp}\*');
    finally
      ProgressPage.Hide;
    end;
  end;
  Result := True;
end;
//-------------------------------------------------------------------
procedure CurStepChanged(CurStep: TSetupStep);
begin
  if CurStep = ssInstall then
  begin
    //MinimizeButtonClick() is called here as the Wizard flashes up for a second
    // and minimizing it makes that 1/2 a second instead...
    MinimizeButtonClick();
    Abort();
  end;
end;

然后我更改了 "Ready" 页面上的文本以适合使用 [消息] 部分。

结果是:

  • 一个向导页面询问用户是否要继续
  • 一个向导页面告诉用户 "please wait..." 在提取临时文件时
  • 一旦文件被解压缩,向导就会隐藏,临时文件夹中的 MyScript.exe 是 运行
  • 一旦 MyScript.exe 完成,向导就会干净地退出并删除临时文件
  • 将文件“安装”到 {tmp},而不是使用 ExtractTemporaryFiles
  • 执行从Run section解压到{tmp}的文件(或安装文件后使用AfterInstall参数或CurStepChanged触发Pascal脚本代码);
  • Uninstallable设置为no
  • CreateAppDir设置为no
  • 使用 [Messages] section 编辑过于以安装程序为中心的向导文本,无法满足您的需要。
[Setup]
Uninstallable=no
CreateAppDir=no

[Files]
Source: "dist\*"; DestDir: {tmp}; Flags: recursesubdirs

[Run]
FileName: "{tmp}\MyScript.exe"

备注:

  • 当“安装程序”关闭时,{tmp} 文件夹被自动删除;
  • 安装到新的空文件夹时不需要 ignoreversion 标志。

相关问题:


如需回答您的字面问题,请参阅 . Or a more generic question on the topic: Inno Setup: How to modify long running script so it will not freeze GUI?