A: 

ShellExecuteEx with SEE_MASK_NOCLOSEPROCESS will (among other things) give you a handle to the new process. You can do a WaitForSingleObject on that handle, which will be signaled when it terminates. BTW, for a GUI program, this is almost always a bad idea -- making your GUI unresponsive until another program exits is really a poor idea.

Jerry Coffin
A: 

code:

SHELLEXECUTEINFO sei = {0};

sei.cbSize = sizeof (SHELLEXECUTEINFO);
sei.fMask  = SEE_MASK_NOCLOSEPROCESS;
sei.lpVerb = "open";
sei.lpFile = "notepad.exe";
sei.nShow  = SW_SHOWNORMAL;

if (ShellExecuteEx (&sei))
{
   WaitForSingleObject (sei.hProcess, INFINITE);
}

As Jerry points out, this is bad for your own GUI. But if the process you launch, directly or indirectly, does a broadcast SendMessage then this can cause catastrophic deadlock, because your process has a window but isn't pumping any messages: the launched process is waiting for your code to handle its message, and you're waiting for it. Clang...

You could use MsgWaitForMultipleObjects instead, or better still, split the launch-and-wait off into a thread and simply disable any part of your UI you don't want the user to interact with.

Bob Moore
A: 

If you just want to launch a process, you don't have to use ShellExecuteEx, use CreateProcess instead. Here is an untested example:

std::wstring commandLine = L"Notepad2.exe"
std::wstring::size_type length = commandLine.size();
boost::scoped_array<WCHAR> buffer(new WCHAR[length + 1]);
std::copy(commandLine.begin(), commandLine.end(), buffer.get());
buffer[length] = L'\0';
STARTUPINFO startupInfo;
ZeroMemory(&startupInfo, sizeof startupInfo);
startupInfo.cb = sizeof startupInfo;
PROCESS_INFORMATION processInfo;
CreateProcess(NULL, buffer.get(), NULL, NULL, FALSE, 0, NULL, NULL, &startupInfo, &processInfo);
CloseHandle(processInfo.hThread);
WaitForSingleObject(processInfo.hProcess, INFINITE);
CloseHandle(processInfo.hProcess);
Philipp