Inno Setup - 在自定义页面上复制带有进度条的文件

Posted

技术标签:

【中文标题】Inno Setup - 在自定义页面上复制带有进度条的文件【英文标题】:Inno Setup - Copy Files with Progress Bar on a custom page 【发布时间】:2020-09-29 15:38:43 【问题描述】:

我目前正在开发一个更新我们公司软件的程序。

我让用户在“CreateInputDirPage”中选择已安装程序的位置和备份位置

目前我正在为两个目录的选择创建一个掩码:

SelectPathPage := CreateInputDirPage(PreviousPageId, 'Text 1', 'Text 2.', 'Text 3', False, 'New Folder'); SelectPathPage.Add('Path to company program'); SelectPathPage.Add('Path to backup folder');

然后我将使用现有文件验证第一个文件夹是否包含我们公司的程序。 现在我想将第一个选择复制到备份文件夹中的一个新子文件夹。

我从another question 找到了用于复制文件的示例代码: DirectoryCopy(SelectPathPage.Values[0], SelectPathPage.Values[1]);

这似乎适用于“NextButtonClick”-Function。

如何在“SelectPathPage”后的单独掩码上复制文件夹和文件夹的内容 - 带有进度条的掩码,并在复制完成后使下一步按钮可用。 它应该类似于带有进度条的“安装”-Mask。 甚至可以在 Inno Setup 的自定义掩码中创建类似的东西吗?

提前致谢

【问题讨论】:

这是可能的,但工作量很大。将这些文件添加到标准安装过程(和整体安装进度条)怎么样? 感谢您的快速回复@MartinPrikryl 据我了解,使用自定义掩码选择文件夹是不可能的。我尝试归档以下内容:1.) 选择两个文件夹 2.) 将第一个文件夹备份到第二个文件夹 3.) 删除第一个文件夹 4.) 将新版本的应用程序安装到第一个文件夹 我不明白您所说的“使用自定义掩码选择文件夹时”是什么意思 首先我很抱歉我的英语不好。谢谢你试图帮助我。面具我的意思是佩奇。如果我没记错的话,那么我不能将文件部分用于我尝试归档的任务。 (要备份现有文件夹,运行安装程序的用户在我的自定义页面中预先选择了该文件夹)我还在安装程序的后续步骤中使用 [File]-Section。 有可能。我发现进度条无论如何都不适用于外部文件。 - 所以回到你最初想做的事情。如果您对每个文件的进度条感到满意,那将相当容易。如果在处理(大)文件时需要它进行,那就更复杂了。 【参考方案1】:

使用CreateOutputProgressPage 创建进度页面。

并将DirectoryCopy函数从Copying hidden files in Inno Setup修改为推进页面进度。

要计算总大小(设置进度条的最大值),代码需要Inno Setup get directory size including subdirectories中的GetDirSize函数。

[Code]

const
  ProgressRatio = 1024;

procedure DirectoryCopyWithProgress(
  SourcePath, DestPath: string; ProgressPage: TOutputProgressWizardPage);
var
  FindRec: TFindRec;
  SourceFilePath: string;
  DestFilePath: string;
  Size: Int64;
begin
  if FindFirst(SourcePath + '\*', FindRec) then
  begin
    try
      repeat
        if (FindRec.Name <> '.') and (FindRec.Name <> '..') then
        begin
          SourceFilePath := SourcePath + '\' + FindRec.Name;
          DestFilePath := DestPath + '\' + FindRec.Name;
          ProgressPage.SetText(SourceFilePath, DestFilePath);
          if FindRec.Attributes and FILE_ATTRIBUTE_DIRECTORY = 0 then
          begin
            Size := Int64(FindRec.SizeHigh) shl 32 + FindRec.SizeLow;
            if FileCopy(SourceFilePath, DestFilePath, False) then
            begin
              Log(Format('Copied %s to %s with %s bytes', [
                SourceFilePath, DestFilePath, IntToStr(Size)]));
            end
              else
            begin
              Log(Format('Failed to copy %s to %s', [
                SourceFilePath, DestFilePath]));
            end;
          end
            else
          begin
            Size := 0;
            if DirExists(DestFilePath) or CreateDir(DestFilePath) then
            begin
              Log(Format('Created %s', [DestFilePath]));
              DirectoryCopyWithProgress(
                SourceFilePath, DestFilePath, ProgressPage);
            end
              else
            begin
              Log(Format('Failed to create %s', [DestFilePath]));
            end;
          end;

          Size := Size / ProgressRatio;
          ProgressPage.SetProgress(
            ProgressPage.ProgressBar.Position + Longint(Size),
            ProgressPage.ProgressBar.Max);
        end;
      until not FindNext(FindRec);
    finally
      FindClose(FindRec);
    end;
  end
    else
  begin
    Log(Format('Failed to list %s', [SourcePath]));
  end;
end;

function SelectPathPageNextButtonClick(Sender: TWizardPage): Boolean;
var
  SourcePath: string;
  DestPath: string;
  ProgressPage: TOutputProgressWizardPage;
  TotalSize: Longint;
begin
  ProgressPage := CreateOutputProgressPage('Copying files...', '');
  SourcePath := TInputDirWizardPage(Sender).Values[0];
  DestPath := TInputDirWizardPage(Sender).Values[1];
  TotalSize := GetDirSize(SourcePath) / ProgressRatio;
  Log(Format('Total size is %s', [IntToStr(TotalSize)]));
  ProgressPage.SetProgress(0, TotalSize);
  ProgressPage.Show;
  try
    DirectoryCopyWithProgress(SourcePath, DestPath, ProgressPage);
  finally
    ProgressPage.Hide;
    ProgressPage.Free;
  end;
  Result := True;
end;

procedure InitializeWizard();
var
  SelectPathPage: TInputDirWizardPage;
begin
  SelectPathPage :=
    CreateInputDirPage(
      wpSelectDir, 'Text 1', 'Text 2.', 'Text 3', False, 'New Folder');
  SelectPathPage.Add('Path to company program');
  SelectPathPage.Add('Path to backup folder');
  SelectPathPage.OnNextButtonClick := @SelectPathPageNextButtonClick;
end;

【讨论】:

以上是关于Inno Setup - 在自定义页面上复制带有进度条的文件的主要内容,如果未能解决你的问题,请参考以下文章

Inno Setup - #define 指令 - 如何使用先前定义的变量?

Inno Setup 安装完成后,默认不重启

Inno Setup打包带有MSI文件的程序

Inno 设置中序列号的自定义页面

inno setup卸载应用程序之前启动另一应用程序

inno setup读取注册表遇到的一个坑