3

I'm currently working on a program that updates our companys software.

I'm letting a User chose the location of the installed program and a backup location in an "CreateInputDirPage"

Currently I'm creating a mask for the selection of the two directorys:

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

Then I'm validating with existing files if the first Folder indead holds our companys program. Now I want to copy the first selection to a new subfolder in the Backup-Folder.

I found this sample code from another question for copying the files: DirectoryCopy(SelectPathPage.Values[0], SelectPathPage.Values[1]);

Which seems to work with the "NextButtonClick"-Function.

How can I copy the folder and the content of the folder on a seperate mask after the "SelectPathPage"-Mask with a progress bar and making the next button available when the copy is finished. It should be similar to the "Install"-Mask with the progress bar. Is it even possible to create something like this in a custom mask in Inno Setup?

Thanks in Advance

Holt
  • 174
  • 1
  • 8
  • It's possible, but lot of work. What about adding those files to the standard installation process (and the overall installation progress bar)? – Martin Prikryl Jun 10 '20 at 09:41
  • Thanks for your quick reply @MartinPrikryl As far as I understood it's not possible when using a custom mask to select the folder. I try to archive the following: 1.) Select both Folders 2.) Backup the first to the second folder 3.) Delete the first folder 4.) Install the new Version of the application.to the first folder – Holt Jun 10 '20 at 10:11
  • I do not understand what you mean by *"when using a custom mask to select the folder"*. – Martin Prikryl Jun 10 '20 at 10:21
  • First of all I'm sry for my bad English. Thank you for trying to help me. With Mask I meant Page. If I'm not mistaken, then I can't use the files section for the task that I try to archive. (To back up an existent folder, that got preselected in my custom page by the User that runs the installer) I'm also using the [File]-Section in a later step of the installer. – Holt Jun 10 '20 at 10:25
  • 1
    It is possible. I've found out that the progress bar does not work with the external files anyway. – So back to what you wanted to do originally. If you are okay with the bar progressing once per file, it's rather easy. If need it to progress while coping (large) file, it more complicated. – Martin Prikryl Jun 10 '20 at 11:13
  • First of all: Thank you very much for your help, I really appreciate it. I have multiple Files (7500 small ones), so 1 by 1 is totally fine. – Holt Jun 10 '20 at 12:34

1 Answers1

2

Use CreateOutputProgressPage to create the progress page.

And modify the DirectoryCopy function from Copying hidden files in Inno Setup to advance the progress on the page.

To calculate the total size (to set the maximum of the progress bar), the code needs GetDirSize function from Inno Setup get directory size including subdirectories.

[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;

enter image description here

enter image description here

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992