I have a very frustrating bug in an application I am working on. The routine is supposed to do something in one window, and then return focus to the other at the end of the method, but when I started to use a large data set the other day, the focus stopped returning at the end. I stepped through the code one line at a time, and the errors stopped. so, i figure its a timing issue of some kind. I trace through until i find what i suspect is the culprit. A call to ShellExecute(…), that terminates an image editor i use.
(http://msdn.microsoft.com/en-us/library/bb762153(VS.85).aspx)
Now, if I step past this call, and then continue to run the program, everything works fine, but if I just run past this line, the error occurs. how can this be? I have a call to SetFocus() at the very end of this method. shouldnt the program hit this no matter what?
This is all so very frustrating…
First thing that should be clear is that Win32 API calls that are related to windows/messages/focus and etc. do not depend on timing.
Every thread has its own window/messaging subsystem, there’s no race conditions here.
What you describe is something else. You actually launch another process (application), which runs concurrently with yours.
Note that
ShellExecuteis an asynchronous function. It returns immediately after creating the process, and from now on your application and the process you’ve created run concurrently.Now, since only one window in the system may have a focus at a time – it’s very likely that the process you’ve created just steals the focus from you.
In order to avoid this – you should first wait for that process to finish working, and only then restore the focus to your window and continue working.
For this you have to obtain the handle of the created process, and call a Win32 waiting function on it.
ShellExecutedoesn’t return you the handle of the created process. HoweverShellExecuteEx– does.BTW it also allows you to launch a process with instruction for it not to show the UI, if this is what you want.
You should write it like this:
This should be helpful
P.S. Of course you should close the handle of the created process. That is,
CloseHandlemust be called afterWaitForSingleObject.