简体   繁体   English

等待Windows上的进程或stdout

[英]Waiting for a process or stdout on Windows

I am firing off a process with CreateProcess, and I want to wait for the process to finish, or for anything to be written to standard out, which is being piped through an anonymous pipe. 我正在使用CreateProcess启动一个进程,我想等待进程完成,或者要将任何内容写入标准输出,这是通过匿名管道传输的。 The code below doesn't work, as WaitForMultipleObjects keeps returning for the stdout pipe, even though there is nothing to read. 下面的代码不起作用,因为WaitForMultipleObjects继续为stdout管道返回,即使没有什么可读。 Is there a way to wait for a pipe? 有没有办法等待管道? I can't wait for a read, as I need to also continue if the process finishes. 我等不及阅读了,因为如果流程结束,我还需要继续阅读。 I also cannot wait until the process is complete without checking the pipe, as it might overflow. 我也不能等到过程完成而没有检查管道,因为它可能会溢出。 Any ideas? 有任何想法吗?

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;
        }
    }
}

Pipes are not waitable objects, so you cannot use them in the WaitFor...() functions. 管道不是可等待的对象,因此您不能在WaitFor...()函数中使用它们。 You can either: 你可以:

  1. Use WaitForSingleObject() to wait on just the process handle, and give it a timeout so your loop wakes up periodically, then it can call PeekNamedPipe() to check the pipe for data. 使用WaitForSingleObject()只等待进程句柄,并给它一个超时,以便你的循环周期性地唤醒,然后它可以调用PeekNamedPipe()来检查管道的数据。

  2. Do the pipe reading in a separate thread, letting the reading block when no data is available, and then terminate the thread when the pipe is closed. 管道读取在一个单独的线程中,当没有数据可用时让读取块,然后在管道关闭时终止线程。 Then you can use WaitForMultipleObjects() to wait on the process and thread handles. 然后,您可以使用WaitForMultipleObjects()来等待进程和线程句柄。

  3. Don't wait on the process handle at all. 不要等待进程句柄。 Just have your loop read from the pipe, blocking when no data is available, until the reading fails when the pipe is closed. 只需从管道读取循环,在没有数据可用时阻塞,直到管道关闭时读取失败。 This is the approach Microsoft's example uses. 这是Microsoft的示例使用的方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM