перенаправить стандартный вывод дочернего процесса в стандартный процесс родительского процесса

0

Я хочу создать консольное приложение Windows, которое запустит дочерний процесс с командной строкой cmd с командной строкой и отобразит результат, созданный дочерним процессом.

Вывод дочернего процесса должен быть прочитан родительским процессом, поэтому мне нужно подключить stdout дочернего процесса к stdin родительского процесса. Затем родительский процесс будет читать из своего stdin вывод из дочернего процесса, который ребенок записывает на его stdout. Родительский процесс отобразит дочерний вывод в родительский stdout.

В дочернем процессе будет выполняться команда dir Windows с командной оболочкой cmd.

Моя текущая версия не отображает вывод команды dir. Родительский процесс не отображает никакого вывода, кроме выхода из system("pause"); ,

Мой основной процесс:

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;
}
  • 0
    Вы знаете, где блокируется родительский процесс?
Теги:
child-process

1 ответ

3
Лучший ответ

В коде есть несколько ошибок, здесь работает очищенный пример.

Сделанные изменения: объединить набор труб в один массив и создать перечисления для обозначения того, что имеет какую-то цель, делает его намного яснее, чем называть что-то "StdOutRead" и "StdOutWrite".

Создала структуру SECURITY_ATTRIBUTES, чтобы мы могли настроить каналы для наследования и добавили код, чтобы предотвратить половину родительских сторон наследуемых труб.

Удалил флаг STARTF_USESTDHANDLES из процесса.

Указал каталог для процесса для выполнения DIR.

Убедитесь, что мы закрываем все ручки, которые мы не используем, как только процесс запускается в родительском.

Наконец, я заставил его слить файл 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;
}
  • 0
    Большое спасибо !!!!

Ещё вопросы

Сообщество Overcoder
Наверх
Меню