我正在使用 CreateProcess 启动一个进程,并且我想等待该进程完成,或者等待任何内容写入标准输出,该标准输出通过匿名管道进行传输。下面的代码不起作用,因为 WaitForMultipleObjects 不断返回标准输出管道,即使没有任何内容可读取。有没有办法等待管道?我迫不及待地想阅读,因为如果该过程完成,我还需要继续。我也不能等到该过程完成而不检查管道,因为它可能会溢出。有任何想法吗?
if (::CreateProcess(
(!application_name.empty() ? application_name.c_str() : NULL), // Application/Executable name, if supplied.
lpCommandLine, // Arguments or Executable and Arguments
NULL, // Process Attributes
NULL, // Thread Attributes
TRUE, // Inherit handles
CREATE_NO_WINDOW, // Create flags
NULL, // Environment (Inherit)
current_directory.c_str(), // Working Directory
&m_startup_info, // Startup Info
&process_info // Process Info
))
{
HANDLE handles[2];
bool waiting = true;
handles[0] = process_info.hProcess;
handles[1] = m_read_stdout; // previously created with CreatePipe. One end handed to CreateProcess
// Must process stdout otherwise the process may block if it's output buffer fills!!
while (waiting)
{
DWORD r = ::WaitForMultipleObjects(2, handles, FALSE, INFINITE);
switch (r)
{
case WAIT_OBJECT_0+0:
waiting = false;
break;
case WAIT_OBJECT_0+1:
AppendSTDOUTFromProcess(output);
break;
default:
ATLASSERT(FALSE);
break;
}
}
}
Run Code Online (Sandbox Code Playgroud)
管道不是可等待对象,因此不能在WaitFor...()函数中使用它们。您可以:
用于WaitForSingleObject()仅等待进程句柄,并给它一个超时,以便循环定期唤醒,然后它可以调用PeekNamedPipe()以检查管道中的数据。
在单独的线程中进行管道读取,当没有可用数据时让读取阻塞,然后在管道关闭时终止线程。然后您可以使用WaitForMultipleObjects()等待进程和线程句柄。
根本不要等待进程句柄。只需让循环从管道中读取数据,在没有可用数据时阻塞,直到管道关闭时读取失败。这就是Microsoft 的示例所使用的方法。