在子进程处于活动状态时读取子进程的输出

read child process's output while it is alive

本文关键字:子进程 读取 输出 活动状态      更新时间:2023-10-16

我创建了两个管道

saAttr.bInheritHandle = TRUE; 
...
CreatePipe(&childStdOut_Rd, &childStdOut_Wr, &saAttr, 0);
CreatePipe(&childStdErr_Rd, &childStdErr_Wr, &saAttr, 0);

然后我用下一个启动信息创建了子进程:

                        STARTUPINFO si;
                        ZeroMemory(&si, sizeof(si));
                        si.cb = sizeof(STARTUPINFO);
                        si.dwFlags     = STARTF_USESHOWWINDOW;
                        si.wShowWindow = SW_MINIMIZE;
                        si.hStdError   = childStdErr_Wr;
                        si.hStdOutput  = childStdOut_Wr;
                        si.hStdInput   = INVALID_HANDLE_VALUE;
                        si.dwFlags    |= STARTF_USESTDHANDLES;

然后关闭父进程中的写入句柄: 关闭手柄(childStdErr_Wr); 关闭手柄(childStdOut_Wr);

我等待子进程完成

WaitForSingleObject(pi.hProcess, INFINITE);

当我在MSDN上阅读时,我可以通过以下方式阅读chil process的stdout:

for (;;) 
{ 
    BOOL bSuccess = ReadFile(childStdOut_Rd, chBuf, bufsize, &dwRead, NULL);
    if(!bSuccess || dwRead == 0) break; 
    bSuccess = WriteFile(hParentStdOut, chBuf, dwRead, &dwWritten, NULL);
    if (!bSuccess) break; 
} 

问:但是我必须在哪里放置代码才能读取孩子的输出?


为什么我不能用这些管道读取 cout 和 printf?

像这样我猜..

ChildProcess -- main.cpp

#include <iostream>
#include <windows.h>

int main()
{
    HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
    if (!hOut)
        return 0;
    DWORD WriteCount = 0;
    char Buffer[1024] = {0};
    strcat(&Buffer[0], "Hello? Momma?!");
    int Length = strlen(Buffer);
    for (int i = 0; i < 10; ++i)
    {
        if (!WriteFile(hOut, Buffer, Length, &WriteCount, 0))
            break;
    }
    return 0;
}

父进程 -- 主进程.cpp

#include <iostream>
#include <windows.h>
void RedirectIO(HANDLE &hRead, HANDLE &hWrite)
{
    SECURITY_ATTRIBUTES attr;
    ZeroMemory(&attr, sizeof(attr));
    attr.nLength = sizeof(attr);
    attr.bInheritHandle = true;
    CreatePipe(&hRead, &hWrite, &attr, 0);
    SetHandleInformation(hRead, HANDLE_FLAG_INHERIT, 0);
}
bool CreateChild(std::string CommandLine, DWORD WaitTime, HANDLE hInRead, HANDLE hOutWrite)
{
    STARTUPINFO SI;
    PROCESS_INFORMATION PI;
    ZeroMemory(&SI, sizeof(SI));
    ZeroMemory(&PI, sizeof(PI));
    SI.cb = sizeof(SI);
    SI.hStdError = hOutWrite;
    SI.hStdInput = hInRead;
    SI.hStdOutput = hOutWrite;
    SI.dwFlags |= STARTF_USESTDHANDLES;
    bool success = CreateProcess(0, const_cast<char*>(CommandLine.c_str()), 0, 0, true, NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW, 0, 0, &SI,&PI);
    if (success)
    {
        WaitForSingleObject(PI.hProcess, WaitTime);
        CloseHandle(PI.hProcess);
        CloseHandle(PI.hThread);
    }
    return success;
}
int main()
{
    HANDLE hRead = nullptr;
    HANDLE hWrite = nullptr;
    RedirectIO(hRead, hWrite);
    CreateChild("C:/Users/School/Desktop/ChildProcess/bin/Debug/ChildProcess.exe", INFINITE, nullptr, hWrite);
    DWORD ReadCount = 0;
    char Buffer[1024] = {0};
    std::string data = std::string();
    while(true)
    {
        if (!ReadFile(hRead, Buffer, sizeof(Buffer) / sizeof(char), &ReadCount, 0))
            break;
        if (!ReadCount) break;
        Buffer[ReadCount] = '';
        data.append(&Buffer[0], ReadCount);
        std::cout<<"Read From Child:nn"<<data<<"n";
    }
    return 0;
}

它应该打印Hello? Momma?! 10次。另一种选择是将读数放在WaitForSingleObject之后,这样您就不会立即关闭该过程,并且可以继续与之通信。甚至可以创建一个线程并在该线程中读取,或者让线程生成进程并读取。轮到你了。