我正在使用的安装程序会在PrepareToInstall函数中完成其大部分工作,因为我需要做的所有事情都可能会失败,因此这是处理这些错误的适当位置。通过在函数的结果中传递错误消息,可以自动报告任何故障。安装程序实际上仅复制3个小文件。

问题在于该向导在此功能期间似乎卡住(或没有响应),只是显示一个标题为“正在准备...的空白页”,而实际上,它正在经历我的安装过程。

我想通过一个简单的过程ShowProgress(const S: String);向用户显示进度,该过程向用户显示其实际操作。我怎样才能做到这一点?

这就是我进行安装的方式,我想将每个调用包装到Log() ...

function PrepareToInstall(var NeedsRestart: Boolean): String;
var
  R: Integer;
begin
  Result:= '';
  try
    Log('Doing this...');
    R:= DoThis;
    case R of
      0: begin
        Result:= '';
      end;
      1: begin
        Result:= 'Error message 1 was raised while doing this.';
      end;
      else begin
        Result:= 'Unexpected error doing this: ' + IntToStr(R);
      end;
    end;

    if Result = '' then begin
      Log ('Doing that...');
      R:= DoThat;
      case R of
        0: begin
          Result:= '';
        end;
        1: begin
          Result:= 'Error message 1 was raised while doing that.';
        end;
        else begin
          Result:= 'Unexpected error doing that: ' + IntToStr(R);
        end;
      end;
    end;

    if Result = '' then begin
      Log ('Doing something else...');
      R:= DoSomethingElse;
      case R of
        0: begin
          Result:= '';
        end;
        1: begin
          Result:= 'Error message 1 was raised while doing something else.';
        end;
        else begin
          Result:= 'Unexpected error doing something else: ' + IntToStr(R);
        end;
      end;
    end;

    //A few more blocks like above

    //Error logging
    if Result <> '' then begin
      Log('FAILURE: '+Result);
    end;

  except
    Result:= 'EXCEPTION';
    Log('EXCEPTION');
  end;
end;

最佳答案

我混合了大家的所有答案,并找到了该问题的另一种可能的解决方案。

我知道这不是所谓的“优雅解决方案”。
无论如何,这是一个快速的解决方案,可以避免您使用管理安装程序和DLL之间的通信的自定义控件开发单独的DLL。

以下方法描述了如何创建自定义页面,该页面是PrepareToInstall设置阶段显示的Page Inno Setup的副本。
此副本必须具有与原始副本相同的外观,并带有进度条和标签,开发人员可以使用该标签来指示PrepareToInstall设置阶段的当前步骤。

让我们看一些代码。
首先,准备自定义页面:

[Code]
var
  PrepareToInstallWithProgressPage : TOutputProgressWizardPage;

现在定义PrepareToInstall函数以添加我们的自定义内容:

function PrepareToInstall(var NeedsRestart: Boolean): String;
var
  ResultCode:   Integer;
begin
  PrepareToInstallWithProgressPage.SetProgress(0, 0);
  PrepareToInstallWithProgressPage.Show;

  try
    // First preinstallation step: suppose to kill currently app you are going to update
    PrepareToInstallWithProgressPage.SetText('Exiting MyApp Running Instances'), '');

    ExecuteCmd('taskkill', '/F /IM MyApp');
    // Set progress bar to 10%
    PrepareToInstallWithProgressPage.SetProgress(1, 10);

    // Second preinstallation step
    // DoSomething usefull...
    // Set progress bar to 20% after done
    PrepareToInstallWithProgressPage.SetProgress(2, 10);

    // ...do other preinstallation steps till the end
    PrepareToInstallWithProgressPage.SetProgress(10, 10);
  finally
    PrepareToInstallWithProgressPage.Hide;
  end;
end;

在此安装阶段,我们完成了准备安装阶段的步骤,因此会暂时显示Inno Setup的默认PrepareToInstall页面。

现在,用户可能无法理解页面的变化,因为我们的PrepareToInstallWithProgressPage具有与原始页面相同的外观。

为了让我们的页面具有相同的外观和感觉,我们可以使用SetupMessage函数获取原始Inno Setup PrepareToInstall页面的2个字符串。
使用SetupMessage,我们可以避免为自定义页面复制和本地化字符串以复制原始内容。

像这样:

procedure InitializeWizard;
var
  A: AnsiString;
  S: String;
begin
  // The string msgWizardPreparing has the macro '[name]' inside that I have to replace with the name of my app, stored in a define constant of my script.
  S := SetupMessage(msgPreparingDesc);
  StringChange(S, '[name]', '{#MY_APPNAME}');
  A := S;
  PrepareToInstallWithProgressPage := CreateOutputProgressPage(SetupMessage(msgWizardPreparing), A);
end;

希望对您有所帮助。

10-07 19:09