Как правильно запустить процесс и переслать stdin / stdout / stderr?

я использую CreateProcess запустить интерактивный интерпретатор сценариев и хотел бы прозрачно переслать stdin / stdout / stderr от / к интерпретатору.

Моей первой попыткой было настроить STARTUPINFO структура передана CreateProcess лайк

STARTUPINFOA si = { sizeof( si ) };
si.hStdError = ::GetStdHandle( STD_ERROR_HANDLE );
si.hStdOutput = ::GetStdHandle( STD_OUTPUT_HANDLE );
si.hStdInput = ::GetStdHandle( STD_INPUT_HANDLE );
si.dwFlags |= STARTF_USESTDHANDLES;

То есть Я попытался заставить процесс интерпретатора сценария использовать тот же дескриптор для чтения / записи, который используется в моем процессе запуска. Это, похоже, не сработало (я даже не уверен, что эти стандартные дескрипторы могут быть унаследованы).

Вторая идея, основанная на Создание дочернего процесса с перенаправленным вводом и выводом Например, нужно настроить три канала для пересылки всех данных, записанных в любой из каналов. Так как я не знаю, как ждать записи данных в более чем один файл (WaitForMultipleObjects не может синхронизироваться по каналам), я рассматривал три потока, каждый из которых выполняет блокировку ReadFile позвони по трубе.

Я подозреваю, что это может быть излишним, хотя я задаюсь вопросом: есть ли какой-нибудь более простой способ сделать это? Мне вообще не нужно выполнять какую-либо обработку данных, передаваемых из / в интерпретатор сценариев.

Как примечание, в Linux я использую execvp просто заменить текущий процесс на процесс интерпретатора сценариев, но в Windows мне нужно запустить интерпретатор сценариев с основным потоком в приостановленном состоянии (чтобы я мог выполнить некоторое исправление байт-кода), так что даже если _execvp, кажется, доступен в Windows Я, очевидно, должен использовать CreateProcess.

5

Решение

Чтобы ожидать ввода-вывода для более чем одного файла или канала, вы выполняете асинхронные запросы ввода-вывода для каждого из этих файлов, а затем ждете завершения указанных запросов. Что-то вроде этого (не проверено):

HANDLE file1, file2; // initialized somehow

HANDLE events[2];
events[0] = CreateEvent(NULL, TRUE, FALSE, NULL);
events[1] = CreateEvent(NULL, TRUE, FALSE, NULL);

OVERLAPPED overlapped1 = {0};
overlapped1.hEvent = events[0];
OVERLAPPED overlapped2 = {0};
overlapped2.hEvent = events[1];

ReadFile(file1, buffer1, size1, NULL, &overlapped1);
ReadFile(file2, buffer2, size2, NULL, &overlapped2);

WaitForMultipleObjects(2, events, FALSE, INFINITE);

ReadFile а также WaitForMultipleObjects нужно будет вызывать в цикле. Вы проверяете возвращаемое значение WaitForMultipleObjects чтобы узнать, какая операция завершена, используйте GetOverlappedResult чтобы узнать результат этой операции (была ли она выполнена успешно, и если да, сколько байт она получила), обработать данные, вызвать ReadFile для этого дескриптора еще раз, если вы хотите почитать еще немного из него, затем вернитесь к ожиданию. Это несколько похоже на цикл неблокирующих операций ввода-вывода select в линуксе

Еще более продвинутая техника Порты завершения ввода / вывода. Это позволяет иметь пул потоков, обрабатывающий множество асинхронных операций ввода-вывода. Обычно используемый в веб-серверах и тому подобное, вероятно, излишний для вашего случая.

4

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

Всплывающее STARTUPINFO как показывает ОП отлично работает если Вы не пропустите CREATE_NO_WINDOW аргумент в dwFlags аргумент CreateProcess.

1

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector