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

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

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

Дочерний процесс будет запускать Windows dir команда с 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

Решение

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

Внесенные изменения: Консолидировал набор каналов в один массив и создал перечисления для обозначения того, для какой цели он предназначен, что делает его более понятным, чем вызов чего-либо «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;
}
3

Другие решения

Других решений пока нет …