Solved

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

Posted on 2013-01-23
3
957 Views
Last Modified: 2013-01-23
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
Comment
Question by:PMH4514
  • 2
3 Comments
 
LVL 31

Accepted Solution

by:
Zoppo earned 500 total points
ID: 38810236
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
 

Author Comment

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

thank you ZOPPO
0
 
LVL 31

Expert Comment

by:Zoppo
ID: 38810262
:o)

you're welcome ...
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

In days of old, returning something by value from a function in C++ was necessarily avoided because it would, invariably, involve one or even two copies of the object being created and potentially costly calls to a copy-constructor and destructor. A…
Templates For Beginners Or How To Encourage The Compiler To Work For You Introduction This tutorial is targeted at the reader who is, perhaps, familiar with the basics of C++ but would prefer a little slower introduction to the more ad…
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.
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.

910 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

23 Experts available now in Live!

Get 1:1 Help Now