Improve company productivity with a Business Account.Sign Up

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1082
  • Last Modified:

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

Hello

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;
    PROCESS_INFORMATION piProcessInfo;
    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. */
		DWORD dwWait=INFINITE;
		if (SecondsToWait > 0)
		{
			dwWait = SecondsToWait * 1000;
		}

		dwExitCode = WaitForSingleObject(piProcessInfo.hProcess, dwWait);

    }
    else
    {
        /* CreateProcess failed */
        iReturnVal = GetLastError();
    }

    /* Free memory */
    delete[]pwszParam;
    pwszParam = 0;

    /* Release handles */
    CloseHandle(piProcessInfo.hProcess);
    CloseHandle(piProcessInfo.hThread);

    return iReturnVal;
} 

Open in new window

0
PMH4514
Asked:
PMH4514
  • 2
1 Solution
 
ZoppoCommented:
Hi PMH4514,

this is a default behavior since Windows XP. I.e. take a look at http://support.microsoft.com/kb/817611/en-us, 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,

ZOPPO
0
 
PMH4514Author Commented:
perfect! I like it when things make sense.

thank you ZOPPO
0
 
ZoppoCommented:
:o)

you're welcome ...
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Get your problem seen by more experts

Be seen. Boost your question’s priority for more expert views and faster solutions

  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now