【问题标题】:Waiting for a process or stdout on Windows在 Windows 上等待进程或标准输出
【发布时间】:2016-02-19 06:41:20
【问题描述】:

我正在使用 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;
        }
    }
}

【问题讨论】:

标签: c++ windows


【解决方案1】:

管道不是可等待的对象,因此您不能在WaitFor...() 函数中使用它们。您可以:

  1. 使用WaitForSingleObject() 仅等待进程句柄,并给它一个超时,以便循环定期唤醒,然后它可以调用PeekNamedPipe() 来检查管道中的数据。

    李>
  2. 在单独的线程中读取管道,当没有数据可用时让读取阻塞,然后在管道关闭时终止线程。然后您可以使用WaitForMultipleObjects() 等待进程和线程句柄。

  3. 根本不等待进程句柄。只需从管道中读取循环,在没有数据可用时阻塞,直到管道关闭时读取失败。这是Microsoft's example 使用的方法。

【讨论】:

  • 我选择了第一个选项。它最适合原来的代码。谢谢。
  • 嗨,雷米,我有一个问题。如果您在单独的线程中进行管道读取,您如何中断它(例如,如果您需要取消操作,或者优雅地退出当前进程)?
猜你喜欢
  • 2019-08-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-08
  • 2021-05-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多