C++ CreateProcess, wait, main app goes not responding in release mode only

Posted on 2013-01-23
Last Modified: 2013-01-23

I'm using the code below to launch an external EXE to my main application (C++ visual studio 2010, MFC project), and wait for that EXE process to be closed by the user before returning control to the main app.

In so far as launching and waiting for it to close, it works as expected. In debug mode, there are no issues. I find that in release mode there is an issue. What happens is that roughly 8 seconds after launching the external EXE, it seems the main app takes on an "hourglass" cursor.. If I do nothing but interact with the child process and then close it, the main application regains control and everything is good. But, if while the child EXE is open and the main application is showing the hourglass I click anywhere within the main application (which shouldn't even be trying to respond to anything) it crashes immediately with basically a "not responding"..

Here is the code (taken from StackOverflow) used to launch the process and wait. I call it with a wait value of 0 for INFINITE but any wait value longer than 5-8 seconds results in the same. Again the "not responding crash" is only in release build, everything is fine in debug mode.

Any ideas? Is there a better way for me to launch an EXE and wait for it to close before proceeding in the main app?

size_t ExecuteProcess(std::wstring FullPathToExe, std::wstring Parameters, size_t SecondsToWait)
    size_t iMyCounter = 0, iReturnVal = 0, iPos = 0;
    DWORD dwExitCode = 0;
    std::wstring sTempStr = L"";

    /* Add a space to the beginning of the Parameters */
    if (Parameters.size() != 0)
        if (Parameters[0] != L' ')
            Parameters.insert(0,L" ");

    /* The first parameter needs to be the exe itself */
    sTempStr = FullPathToExe;
    iPos = sTempStr.find_last_of(L"\\");
    sTempStr.erase(0, iPos +1);
    Parameters = sTempStr.append(Parameters);

     /* CreateProcessW can modify Parameters thus we allocate needed memory */
    wchar_t * pwszParam = new wchar_t[Parameters.size() + 1];
    if (pwszParam == 0)
        return 1;
    const wchar_t* pchrTemp = Parameters.c_str();
    wcscpy_s(pwszParam, Parameters.size() + 1, pchrTemp);

    /* CreateProcess API initialization */
    STARTUPINFOW siStartupInfo;
    memset(&siStartupInfo, 0, sizeof(siStartupInfo));
    memset(&piProcessInfo, 0, sizeof(piProcessInfo));
    siStartupInfo.cb = sizeof(siStartupInfo);

    if (CreateProcessW(const_cast<LPCWSTR>(FullPathToExe.c_str()),
                            pwszParam, 0, 0, false,
                            CREATE_DEFAULT_ERROR_MODE, 0, 0,
                            &siStartupInfo, &piProcessInfo) != false)
         /* Watch the process. */
		if (SecondsToWait > 0)
			dwWait = SecondsToWait * 1000;

		dwExitCode = WaitForSingleObject(piProcessInfo.hProcess, dwWait);

        /* CreateProcess failed */
        iReturnVal = GetLastError();

    /* Free memory */
    pwszParam = 0;

    /* Release handles */

    return iReturnVal;

Open in new window

Question by:PMH4514
  • 2
LVL 30

Accepted Solution

Zoppo earned 500 total points
ID: 38810236
Hi PMH4514,

this is a default behavior since Windows XP. I.e. take a look at, there you can find this:
If a top-level window stops responding to messages for more than several seconds, the system considers the window to be hung and replaces it with a ghost window that has the same z-order, location, size, and visual attributes. This allows the user to move it, resize it, or even close the application. However, these are the only actions available because the application is actually hung. When in the debugger mode, the system does not generate a ghost window.
So, the trick is to avoid the OS treats your app as 'not responding'.

An easy way to do so is to repeatedly call PeekMessage while waiting for the called process, i.e.:
	MSG msg;
	while( WAIT_TIMOUT == ( dwExitCode = WaitForSingleObject( piProcessInfo.hProcess, 1000 ) )
		// every one second call PeekMessage
		PeekMessage( &msg, NULL, WM_NULL, WM_NULL, PM_NOREMOVE );

Open in new window

(This sample doesn't handle the SecondsToWait, you'll have to add it)

Hope that helps,


Author Comment

ID: 38810246
perfect! I like it when things make sense.

thank you ZOPPO
LVL 30

Expert Comment

ID: 38810262

you're welcome ...

Featured Post

Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

Join & Write a Comment

Errors will happen. It is a fact of life for the programmer. How and when errors are detected have a great impact on quality and cost of a product. It is better to detect errors at compile time, when possible and practical. Errors that make their wa…
C++ Properties One feature missing from standard C++ that you will find in many other Object Oriented Programming languages is something called a Property (…
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.

708 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

15 Experts available now in Live!

Get 1:1 Help Now