我正在使用CreateProcess启动一个进程,我想等待进程完成,或者要将任何内容写入标准输出,这是通过匿名管道传输的。下面的代码不起作用,因为WaitForMultipleObjects继续为stdout管道返回,即使没有什么可读的。 有没有办法等待管道?我无法等待阅读,因为如果流程结束,我还需要继续阅读。 我也不能等到过程完成而没有检查管道,因为它可能会溢出。有什么想法吗?
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;
}
}
}
答案 0 :(得分:3)
管道不是可等待的对象,因此您无法在WaitFor...()
函数中使用它们。你可以:
使用WaitForSingleObject()
等待进程句柄,并给它一个超时,以便定期唤醒你的循环,然后它可以调用PeekNamedPipe()
来检查数据管道。
在单独的线程中读取管道,在没有数据时让读取块,然后在管道关闭时终止线程。然后,您可以使用WaitForMultipleObjects()
等待进程和线程句柄。
根本不要等待进程句柄。只需从管道读取循环,在没有数据可用时阻塞,直到管道关闭时读取失败。这是Microsoft's example使用的方法。