3

I have found in my company's codebase a code to open default mail program using ShellExecute. The code is written long time ago, but I've notice strange behavior on it, the problem only occurs when the debugger is not attached.

if ShellExecute(Handle, PChar('open'), PChar('mailto:donotreply@nonono.com'), nil, nil, SW_SHOWDEFAULT) <= 32 then
begin
  //...
end;

Above is the relevant part of the code. Handle is the Form handle.

To reproduce the problem, simply create a new project, add a button on it and call this code on the button onClick event handler. It is also necessary to not have a default mail installed, so windows will display an message warning about that.

When debugging, the message Z order is higher than the application, so the message box is properly displayed and the user can close this message. When not debugging, the message Z order is lower than the application, so the user has to alt+tab to see that message.

I don't have enough knowledge to understand what is happening nor to state if that behavior is correct or not.

Is there anything I can do to properly display the message box in a higher Z order than my application?
Is this code deprecated? Should I move forward to a different way of doing this, if so, how?

EProgrammerNotFound
  • 2,403
  • 4
  • 28
  • 59
  • What is Handle? .... – David Heffernan Oct 22 '15 at 11:56
  • @DavidHeffernan Fixed, thank you – EProgrammerNotFound Oct 22 '15 at 11:57
  • Obvious first question: Is COM properly initialized on the thread that calls [ShellExecute](https://msdn.microsoft.com/en-us/library/windows/desktop/bb762153.aspx)? The reason for the different behavior is likely, that you're calling [SetForegroundWindow](https://msdn.microsoft.com/en-us/library/windows/desktop/ms633539.aspx) directly or indirectly. Specifically: *"A process can set the foreground window only if one of the following conditions is true: [...] The process is being debugged."* – IInspectable Oct 22 '15 at 12:49
  • @IInspectable I've called `CoInitialize(nil)`. What do you mean by 'properly initialized'? – EProgrammerNotFound Oct 22 '15 at 13:01
  • 2
    *"Properly"* as in *"according to the documentation"*. [ShellExecute](https://msdn.microsoft.com/en-us/library/windows/desktop/bb762153.aspx) should only be called from a single-threaded apartment (STA) thread. `CoInitialize(nil)` (assuming the call succeeds) initializes the COM library for use by an STA thread. – IInspectable Oct 22 '15 at 14:11
  • ShellExecute or ShellExecuteEx are pretty much what you've got available. If it doesn't work to your needs then you've got much room to manoeuvre. – David Heffernan Oct 22 '15 at 16:06
  • @IInspectable I wonder what kind of magic is the debugger doing... – EProgrammerNotFound Oct 22 '15 at 18:21
  • The debugger is implemented in *kernel32.dll*. I doubt there's any magic involved. It's just using its power to make things happen in the same way that it prevents other things from happening. – IInspectable Oct 23 '15 at 07:54

0 Answers0