Solved

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

Posted on 2013-01-23
3
973 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

VMware Disaster Recovery and Data Protection

In this expert guide, you’ll learn about the components of a Modern Data Center. You will use cases for the value-added capabilities of Veeam®, including combining backup and replication for VMware disaster recovery and using replication for data center migration.

Question has a verified solution.

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

Many modern programming languages support the concept of a property -- a class member that combines characteristics of both a data member and a method.  These are sometimes called "smart fields" because you can add logic that is applied automaticall…
This article shows you how to optimize memory allocations in C++ using placement new. Applicable especially to usecases dealing with creation of large number of objects. A brief on problem: Lets take example problem for simplicity: - I have a G…
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…
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.

803 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