3

I create setup for my program using Inno Setup. I have code C# and some wizard page runs it. I want to see "ProgressBar" (style Marquee) when my code C# works a long time. I want to undectend my code C# is working or hanging. How create a "ProgressBar" (style Marquee) in Inno Setup for my code C#. Thank you for any idea.

Example Progress par:

enter image description here

Some code:

[Files]
Source: "GetDataBases.dll"; Flags: dontcopy

[Code]

function ServerOfDataBases(
  scriptName, server, user, password,nameDB: string;
  out strout: WideString): Integer;
  external 'ServerOfDataBases@files:GetDataBases.dll stdcall';

var
  ServerDetailsPage: TInputQueryWizardPage;

function CallDB(scriptName, server, user, password, nameDB: string):string;
var
  retval: Integer;
  str: WideString;
begin  
  retval := ServerOfDataBases(scriptName, server, user, password, nameDB, str); 
  Result:= str; 
end;

procedure InitializeWizard;
var
 ...
begin
  ServerDetailsPage := CreateInputQueryPage(wpWelcome, '', '', '...');
  ServerDetailsPage.Add('Server...', False);
  ...
  ServerDetailsPage.Values[0] := '';
end;

function NextButtonClick(CurPageID: Integer): Boolean;
var
  DataDases: String;
...
begin
  ...  
  if CurPageID = ServerDetailsPage.ID then
  begin
    ...
    DataDases := '';
    scriptName := 'ListDB';
    DataDases := CallDB(
      scriptName, ServerDetailsPage.Values[0], ServerDetailsPage.Values[2],
      ServerDetailsPage.Values[3], '');
     ...
  end;
end;

    
Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
Джирайя
  • 149
  • 2
  • 13

1 Answers1

3

This is not easy. Calling into synchronous function effectively blocks the GUI thread. So you cannot animate the progress bar.

You have to run the lengthy task on a different thread. As it seems to be your DLL, you can modify it to offer an asynchronous API. Something like:

private static Task _task = null;
private static int _outcome;

[DllExport(CallingConvention = CallingConvention.StdCall)]
public static void StartSomething()
{
    // Starts an operation on a different thread
    _task = new Task(() => { Something(); });
    _task.Start();
}

// The operation to run on a different thread
private static void Something()
{
    // The lengthy operation
    Thread.Sleep(10000);
    // Remember the results
    _outcome = 123;
}

[DllExport(CallingConvention = CallingConvention.StdCall)]
public static bool HasSomethingCompleted(out int outcome)
{
    // Check if the operation has completed
    bool result = _task.IsCompleted;
    // And collect its results
    outcome = _outcome;
    return result;
}

And then you can use this from Inno Setup like:

procedure InitializeWizard();
begin
  ServerDetailsPage := CreateInputQueryPage(wpWelcome, '', '', '...');
end;

procedure CallDll;
var
  ProgressPage: TOutputMarqueeProgressWizardPage;
  Outcome: Integer;
begin
  StartSomething;

  ProgressPage := CreateOutputMarqueeProgressPage('Calling DLL', '');
  ProgressPage.Show;
  try
    ProgressPage.ProgressBar.Style := npbstMarquee;
    { wait for the Something to finish }
    while not HasSomethingCompleted(Outcome) do
    begin
      ProgressPage.Animate;
      Sleep(50);
    end;

  finally
    ProgressPage.Hide;
    ProgressPage.Free;
  end;

  MsgBox(Format(
    'Something has finished and the outcome was %d', [Outcome]),
    mbInformation, MB_OK);
end;

function NextButtonClick(CurPageID: Integer): Boolean;
begin
  if CurPageID = ServerDetailsPage.ID then
  begin
    CallDll;
  end;
  Result := True;
end;

enter image description here

For a similar question see:
How to delay without freezing in Inno Setup

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