progress-barinno-setuppascalscript

Correctly timing update of Inno Setup progress bar


I forgotten how to update a progress bar correctly in Inno Setup according to a condition and I wrote a code to update a progress bar I created in Wizard.

The problem is I am getting 95, 96, 97, 98, or 100, 101 for the ProgressBar's last Position and its updating is not same from time to time when I runs my Installer. And the value I used to divide (here it is 6) won't work on all systems similarly as their performance is very different from each system.

I like to know a way to correctly update progress bar without having such problems.

[Files]
Source: "C:\Program Files (x86)\Inno Setup 5\Examples\MyProg.exe"; DestDir: "{app}"; Flags: ignoreversion
Source: "C:\InnoCallback.dll"; DestDir: "{app}"; Flags: ignoreversion
[Code]
Type
  TTimerProc = procedure(HandleW, msg, idEvent, TimeSys: LongWord);

function SetTimer(hWnd, nIDEvent, uElapse, lpTimerFunc: LongWord): LongWord;
  external 'SetTimer@User32.dll stdcall';
function WrapTimerProc(Callback: TTimerProc; ParamCount: Integer): LongWord;
  external 'wrapcallback@{tmp}\InnoCallback.dll stdcall delayload';
function KillTimer(hWnd, nIDEvent: LongWord): LongWord;
  external 'KillTimer@User32.dll stdcall';

var
  TTimer: LongWord;
  ConditionTracker: String;
  P: Integer;
  TestingPB: TNewProgressBar;

procedure Install;
var
  ErrorCode: Integer;
begin
  if ShellExec('Open', 'Timeout.exe', '/T 10', '', SW_HIDE,
               ewWaitUntilTerminated, ErrorCode) then
    ConditionTracker := 'DONE';
end;

procedure UpdateProgressBar(HandleW, msg, idEvent, TimeSys: LongWord);
begin
  if ConditionTracker = 'DONE' then begin
    KillTimer( 0, TTimer);
    TestingPB.State := npbsPaused;
  end else begin
    P := P + 1;
    Log('ProgressBar Position: ' + IntToStr(P div 6));
    TestingPB.Position := P div 6;
    if (P div 6) = 100 then P := 600;
  end;
end;

procedure InitializeWizard;
begin
  TestingPB := TNewProgressBar.Create(WizardForm);
  with TestingPB do begin
    Parent := WizardForm;
    Width := WizardForm.ProgressGauge.Width;
    Top := 200;
    Left := (WizardForm.ClientWidth - Width) div 2;
    Max := 100;
    Position := 0;
    Hide;
    ExtractTemporaryFile('InnoCallback.dll'); 
    P := 0;
  end;
end;

procedure CurPageChanged(CurPageID: Integer);
begin
  if CurPageID = wpSelectTasks then begin
    TestingPB.Show;
    TTimer := SetTimer( 0, 0, 0, WrapTimerProc(@UpdateProgressBar, 4));
    Install;
  end else
    TestingPB.Hide;
end;

Thanks in advance.


Solution

  • The two primary problems are:


    Other problems with your code:


    [Code]
    
    function GetTickCount: DWord;
      external 'GetTickCount@kernel32 stdcall';
    function SetTimer(hWnd, nIDEvent, uElapse, lpTimerFunc: LongWord): LongWord;
      external 'SetTimer@User32.dll stdcall';
    function KillTimer(hWnd, nIDEvent: LongWord): LongWord;
      external 'KillTimer@User32.dll stdcall';
    
    var
      Timer: LongWord;
      Done: Boolean;
      TestingPB: TNewProgressBar;
      InitialTime: DWord;
    
    const
      Duration = 10000;
    
    procedure Install;
    var
      ErrorCode: Integer;
    begin
      if ShellExec('Open', 'Timeout.exe', '/T ' + IntToStr(Duration div 1000), '',
                   SW_HIDE, ewWaitUntilTerminated, ErrorCode) then
      begin
        Done := True;
      end;
    end;
    
    procedure UpdateProgressBar(HandleW, msg, idEvent, TimeSys: LongWord);
    begin
      if Done then
      begin
        KillTimer(0, Timer);
        TestingPB.State := npbsPaused;
        TestingPB.Position := TestingPB.Max;
      end
        else
      begin
        TestingPB.Position := GetTickCount - InitialTime;
      end;
    end;
    
    procedure InitializeWizard;
    begin
      TestingPB := TNewProgressBar.Create(WizardForm);
      with TestingPB do
      begin
        Parent := WizardForm.SelectTasksPage;
        Width := WizardForm.ProgressGauge.Width;
        Left := WizardForm.ProgressGauge.Left;
        Top := ScaleY(200);
        Max := Duration;
        Position := 0;
      end;
    end;
    
    procedure CurPageChanged(CurPageID: Integer);
    begin
      if CurPageID = wpSelectTasks then
      begin
        Timer := SetTimer(0, 0, 100, CreateCallback(@UpdateProgressBar));
        InitialTime := GetTickCount;
        Install;
      end
    end;