Inno Setup: Marquee style progress bar for lengthy synchronous operation in C# DLL

前端 未结 1 829
死守一世寂寞
死守一世寂寞 2021-01-06 12:58

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 lo

1条回答
  •  情话喂你
    2021-01-06 13:21

    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: TOutputProgressWizardPage;
      Outcome: Integer;
    begin
      StartSomething;
    
      ProgressPage := CreateOutputProgressPage('Calling DLL', '');
      ProgressPage.Show;
      try
        ProgressPage.SetProgress(0, 100);
        ProgressPage.ProgressBar.Style := npbstMarquee;
        { wait for the Something to finish }
        while not HasSomethingCompleted(Outcome) do
        begin
          { And pump windows message queue frequently to animate the progress bar }
          ProgressPage.SetProgress(0, 100);
          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;
    

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


    Note that the marquee style progress bar does not work in Inno Setup 6.1. You have to use an older version. See https://groups.google.com/g/innosetup/c/9eisZhaDsJQ.

    0 讨论(0)
提交回复
热议问题