Hope to support 'TApplication' class

50 views
Skip to first unread message

yanghan liu

unread,
Jun 20, 2021, 9:40:02 PM6/20/21
to innosetup
Sometimes we need to do some work in the background but don't want the interface to be frozen. It is a good way to call the ProcessMessage function of TApplication, but the TApplication class is not in the Support Classes of innosetup.

Eivind Bakkestuen

unread,
Jun 20, 2021, 10:55:24 PM6/20/21
to inno...@googlegroups.com
No. It's not a good way in Delphi either. Perhaps describe what you really want to do?

In general, I'd suggest creating a DLL that can run your lengthy operation in a separate thread.


On Mon, Jun 21, 2021 at 11:40 AM yanghan liu <yangh...@gmail.com> wrote:
Sometimes we need to do some work in the background but don't want the interface to be frozen. It is a good way to call the ProcessMessage function of TApplication, but the TApplication class is not in the Support Classes of innosetup.

--
You received this message because you are subscribed to the Google Groups "innosetup" group.
To unsubscribe from this group and stop receiving emails from it, send an email to innosetup+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/innosetup/e1d1ab53-3226-4817-af25-20ceb096e2een%40googlegroups.com.

Luís César Zanetti

unread,
Jun 20, 2021, 11:07:30 PM6/20/21
to inno...@googlegroups.com
I understand what you mean.
An Example: Sometimes in a loop with findFirst, FindNex to create a list of files the installer may freeze.
So you will need to process messages from time to time.
But since there is no TAplication.ProcessMessages class, we can use the API to process the messages.

const
  PM_REMOVE = $0001;

function TranslateMessage(const lpMsg: TMsg): BOOL;
  external 'Translat...@user32.dll stdcall delayload';

function DispatchMessage(const lpMsg: TMsg): Longint;
  external 'Dispatch...@user32.dll stdcall delayload';

function PeekMessage(var lpMsg: TMsg; hWnd: HWND; wMsgFilterMin, wMsgFilterMax, wRemoveMsg: UINT): BOOL;
  external 'PeekMe...@user32.dll stdcall delayload';

procedure ProcessMessages;
var
  Msg: TMsg;
begin
  while PeekMessage(Msg, 0, 0, 0, PM_REMOVE) do
  begin
    TranslateMessage(Msg);
    DispatchMessage(Msg);
  end;
end;


Jordan Russell

unread,
Jun 22, 2021, 6:24:25 PM6/22/21
to innosetup
ProcessMessages is intentionally not exposed because it seems most people who use it or want to use it fail to understand or account for the risk involved. Specifically, there's a problem with reentrancy that can lead to crashes or other undefined behavior.

For example, if the user clicks Next, and in your NextButtonClick handler you call ProcessMessages, the user can click Next again during that ProcessMessages call, resulting in a nested invocation of NextButtonClick. The wizard isn't built to expect that, and your [Code] probably isn't either.

If you really do think you need to process messages, then you need to be extra sure to disable access to the UI, e.g.:

  WizardForm.Enabled := False;
  try
    // ProcessMessages...
  finally
    WizardForm.Enabled := True;
  end;

(Substitute WizardForm with whatever form is currently active.)

My advice, though, is still "don't even try it".
Reply all
Reply to author
Forward
0 new messages