简体   繁体   English

将子进程的stdout重定向到父进程stdin

[英]redirect the stdout of a child process to the parent process stdin

I want to create a Windows console application that will start a child process running the cmd command shell with a command line and display the output created by the child process. 我想创建一个Windows控制台应用程序,该应用程序将启动一个使用命令行运行cmd命令外壳的子进程,并显示该子进程创建的输出。

The output from the child process is to be read by the parent process so I need to connect the stdout of the child process to the stdin of the parent process. 子进程的输出将由父进程读取,因此我需要将子进程的stdout连接到父进程的stdin The parent process will then read from its stdin the output from the child process which the child is writing to its stdout . 然后,父进程将从其stdin读取子进程正在向其stdout写入的子进程的stdout The parent process will display the child output to the parent's stdout . 父进程将显示子输出到父stdout

The child process will run the Windows dir command with the cmd command shell. 子进程将使用cmd命令外壳运行Windows dir命令。

My current version is not displaying the dir command output. 我当前的版本未显示dir命令输出。 The parent process is not displaying any output other than the output from the system("pause"); 父进程除了system("pause");的输出外,不显示任何其他输出system("pause"); .

My main process: 我的主要流程:

int main(int argc,char* argv[])
{
    HANDLE hStdInRead;
    HANDLE hStdInWrite;

    HANDLE hStdOutRead;
    HANDLE hStdOutWrite;
    HANDLE hStdErrWrite;
    if(!CreatePipe(&hStdInRead,&hStdInWrite,NULL,0))
        return 0;
    if(!CreatePipe(&hStdOutRead,&hStdOutWrite,NULL,0))
        return 0;
    if (!DuplicateHandle(GetCurrentProcess(), hStdOutWrite, GetCurrentProcess(), &hStdErrWrite, 0, TRUE, DUPLICATE_SAME_ACCESS))  
    {
        return 0;
    }
    STARTUPINFO si;
    ZeroMemory(&si,sizeof(STARTUPINFO));
    si.cb = sizeof(STARTUPINFO);
    si.wShowWindow = SW_SHOW; 
    si.dwFlags =STARTF_USESHOWWINDOW|STARTF_USESTDHANDLES;
    si.hStdOutput = hStdOutWrite;
    si.hStdError = hStdErrWrite;
    si.hStdInput = hStdInRead;
    PROCESS_INFORMATION pi;
    ZeroMemory(&pi,sizeof(PROCESS_INFORMATION));

    LPSTR cmd = new char[256*sizeof(char)];
    strcpy_s(cmd,256,"C:\\Windows\\cmd.exe /c dir");
    if(CreateProcess(NULL,cmd,NULL,NULL,true,0,NULL,NULL,&si,&pi))
    {
        std::cout<<"OK"<<std::endl;
        CloseHandle(hStdOutWrite);
        CloseHandle(hStdInRead);
        char ReadBuff[4096];
        DWORD ReadNum ;
        ZeroMemory(&ReadBuff,4096);
        while(ReadFile(hStdOutRead,ReadBuff,4096,&ReadNum,NULL))
        {   
           std::cout<<ReadBuff<<std::endl;
        }
        WaitForSingleObject(pi.hProcess,INFINITE);
    }
    system("pause");
    return 0;
}

There are several things wrong with your code, here's a cleaned up example that works. 您的代码有几处错误,这是一个有效的示例。

Changes made: Consolidated the pipe set into one array and created enums to denote which has what purpose, makes it a lot clearer than calling something "StdOutRead" and "StdOutWrite". 所做的更改:将管道集合并为一个数组,并创建枚举来表示目的是什么,使其比调用“ StdOutRead”和“ StdOutWrite”更加清晰。

Created a SECURITY_ATTRIBUTES structure to let us set up the pipes for inheritance, and added code to prevent the parent-side halves of the pipes being inherited. 创建了SECURITY_ATTRIBUTES结构来让我们设置用于继承的管道,并添加了代码以防止继承管道的父级一半。

Removed the STARTF_USESTDHANDLES flag from the process. 从进程中删除了STARTF_USESTDHANDLES标志。

Specified a directory for the process to perform it's DIR on. 指定要执行DIR的进程的目录。

Ensured that we close all the handles we're not using once the process is started in the parent. 确保在父进程中启动该过程后,关闭所有不使用的句柄。

Lastly, I made it drain the file of io in chunks and append the null terminator to the end of a successful buffer so that it can output properly. 最后,我使它以块的形式耗尽io文件,并将空终止符附加到成功缓冲区的末尾,以便可以正确输出。

#define WINDOWS_LEAN_AND_MEAN
#include <Windows.h>
#include <tchar.h>

#include <iostream>
#include <thread>
#include <cassert>

enum { ParentRead, ParentWrite, ChildWrite, ChildRead, NumPipeTypes };

int main(int /*argc*/, char* /*argv*/[])
{
    SECURITY_ATTRIBUTES sa;
    sa.nLength = sizeof(sa);
    sa.bInheritHandle = TRUE;
    sa.lpSecurityDescriptor = nullptr;

    HANDLE pipes[NumPipeTypes];
    if (!CreatePipe(&pipes[ParentWrite], &pipes[ChildRead], &sa, 0))
        return 0;
    if (!CreatePipe(&pipes[ParentRead], &pipes[ChildWrite], &sa, 0))
        return 0;

    // make sure the handles the parent will use aren't inherited.
    SetHandleInformation(pipes[ParentRead], HANDLE_FLAG_INHERIT, 0);
    SetHandleInformation(pipes[ParentWrite], HANDLE_FLAG_INHERIT, 0);

    STARTUPINFO si;
    ZeroMemory(&si, sizeof(STARTUPINFO));
    si.cb = sizeof(STARTUPINFO);
    si.wShowWindow = SW_SHOW;
    si.dwFlags = STARTF_USESHOWWINDOW;
    si.hStdOutput = pipes[ChildWrite];
    si.hStdError = pipes[ChildWrite];
    si.hStdInput = pipes[ChildRead];
    PROCESS_INFORMATION pi;
    ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));

    TCHAR cmd[] = _T("C:\\Windows\\System32\\cmd.exe /c dir c:\\");
    if (!CreateProcess(NULL, cmd, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi))
        return 0;

    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
    CloseHandle(pipes[ChildRead]);
    CloseHandle(pipes[ChildWrite]);
    CloseHandle(pipes[ParentWrite]);

    char ReadBuff[4096 + 1];
    DWORD ReadNum;
    for (;;) {
        auto success = ReadFile(pipes[ParentRead], ReadBuff, sizeof(ReadBuff) - 1, &ReadNum, NULL);
        if (!success || !ReadNum)
            break;
        ReadBuff[ReadNum] = 0;
        std::cout << ReadBuff;
    }
    //system("pause");  use Ctrl+F5 or Debug >> Start Without debugging instead.
    return 0;
}

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

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