Inno Setup: How to modify long running script so it will not freeze GUI?

The output progress pages are designed for providing feedback on longer running operations.

But in order for this to be effective you have to be able to keep Inno updated on your current progress by periodically calling methods on this page.

There is a library that will let you pass an Inno script function as a callback to a DLL, which may be of use. You may also want to look at using the ITDownload script from the same site, which lets you do HTTP access from within Inno itself, avoiding the middle-man.

However Inno is inherently single-threaded and GUI-thread-affine, so calling blocking operations directly will always block the UI without special provision. Running code from within a separate thread is possible (but only within a DLL, and you have to be very careful); other options include making asynchronous calls only, or calls which internally maintain GUI updates, such as Exec.


There are two ways to improve the experience (they are different from an API point of view only, internally both do the same – they pump a Windows message queue):

  1. Use TOutputProgressWizardPage to present an operation progress. Its SetProgress method internally calls VCL TApplication.ProcessMessages, which pumps Windows message queue.

    Use CreateOutputProgressPage to create the page.

    Some examples:

    • Inno Setup Get progress from .NET Framework 4.5 (or higher) installer to update progress bar position
    • How to delay without freezing in Inno Setup
    • Make Inno Setup Installer report its installation progress status to master installer
    • Inno Setup ExtractTemporaryFile causes wizard to freeze
    • Inno Setup torrent download implementation
    • Inno Setup - How to add multiple arc files to decompress?
  2. Explicitly pump the Windows message queue by calling WinAPI DispatchMessage.

    For some examples, see AppProcessMessage function in:

    • MySQL server discovery on LAN by listening port (Inno Setup)
    • How to execute 7zip without blocking the Inno Setup UI?
    • and others

In both cases, you have to add calls that trigger the message queue pumping. Usually within some loop that does the processing.

In some cases, you won't be able to do that. For example, when you use a blocking call to an external application (e.g. using Exec or ShellExec) to do the processing. You can workaround that by scheduling a timer that will be regularly triggered, while the function is running.

This approach is used by some examples linked above, namely:

  • Make Inno Setup Installer report its installation progress status to master installer
  • Inno Setup torrent download implementation