Sometimes you want to spawn an external process and wait until it's completed before continuing with your application. Both CreateProcess and ShellExecuteEx give you a handle to the thread Windows created to run the spawned application. You can use this thread handle, in conjunction with the WaitForSingleObject API function, to pause execution of your program until the spawned application has terminated. To do so, simply pass the thread handle of the spawned process to WaitForSingleObject and Windows does the rest. Here's how the code would look if you're using the CreateProcess function:
STARTUPINFO si;
PROCESS_INFORMATION pi;
memset(&pi, 0, sizeof(pi));
memset(&si, 0, sizeof(si));
si.cb = sizeof(si);
int res = CreateProcess(0, "notepad.exe",
0, 0, 0, 0, 0, 0, &si, &pi);
if (res) {
WaitForSingleObject(pi.hThread,
INFINITE);
SetFocus();
}
If CreateProcess is successful, the hThread member of the PROCESS_INFORMATION
structure contains the thread handle for the new process. We pass that thread
handle to WaitForSingleObject with a timeout value of INFINITE. The host
application will now pause execution until the spawned application is closed.
ShellExecuteEx can also be used to wait for a spawned process. Here's an
example of displaying a text file in Windows Notepad and waiting for Notepad to
close before allowing the application to continue:
SHELLEXECUTEINFO si;
memset(&si, 0, sizeof(si));
si.cbSize = sizeof(si);
si.hwnd = Handle;
si.lpVerb = "open";
si.lpFile = "test.txt";
si.nShow = SW_NORMAL;
si.fMask = SEE_MASK_NOCLOSEPROCESS;
bool res = ShellExecuteEx(&si);
if (res)
WaitForSingleObject(si.hProcess,
INFINITE);
Although we haven't talked about ShellExecuteEx in any detail, it's easy to see
how this function works compared to ShellExecute. Rather than sending the
parameters directly to the function, ShellExecuteEx requires you to fill out a
structure with the required information. If ShellExecuteEx returns
successfully, the hProcess member of the SHELLEXECUTEINFO structure contains
the process handle of the spawned application. This member is only valid if the
fMask member contains the SEE_MASK_NOCLOSEPROCESS flag. You can pass the
process handle to WaitForSingleObject, as shown in the previous example.