Why does WaitForSingleObject() after CreateProcess() show the AppStarting cursor?

4.6k views Asked by At

I've written a simple launcher that looks up the actual program and then executes it. This works fine, but there is one issue: Windows displays the "pointer with hourglass" cursor for about give seconds. This does not happen if I launch the program directly.

I tried setting sinfo.dwFlags = STARTF_FORCEOFFFEEDBACK but this did not help. I guess that's because it's my program that somehow needs to disable the cursor and the program I start does that fine (it creates a proper window etc.).

This is the relevant code from my application. I do not have any threads or any other fancy stuff (the sole purpose of the program is to launch another program and pass on the exit code to its caller in case it cares about it):

STARTUPINFO sinfo = {0};
PROCESS_INFORMATION pinfo = {0};
if (!CreateProcess(program, buf, NULL, NULL, FALSE, 0, NULL, NULL, &sinfo, &pinfo)) {
    Fail("Could not launch Vim");
}
if (WaitForSingleObject(pinfo.hProcess, INFINITE) == WAIT_FAILED) {
    Fail("WaitForSingleObject");
}
2

There are 2 answers

1
ThiefMaster On BEST ANSWER

Apparently Windows expects a Windows program to process messages and does not consider it fully started before that point, which is why it shows the appstarting cursor.

Adding the following code to process a single dummy message solved the problem:

MSG msg;
PostMessage(NULL, WM_NULL, 0, 0);
GetMessage(&msg, NULL, 0, 0);
3
selbie On

Your program is showing the hour-glass icon because your UI thread is hanging as a result of being stalled on the WaitForSingleObject call. Remember, WaitForSingleObject does not return until after the child process exits. You could substitute the Wait call with a Sleep and get the same effect.

You have some options:

  1. Use MsgWaitForMultipleObjects instead of WaitForSingleObject. This is the more formal way to pump messages and wait at the same time instead of the PostMessage/GetMessage thing you suggest in your own answer.

  2. Do the Wait call on another thread. When the thread returns, it PostMessage something to your UI thread to indicate it is done.

In both of the above cases, the UI will become responsive to clicks and input events while the child process is still happening. You will need to code your UI thread to handle this as appropriate (if it's warranted).