я использую 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.
Чтобы ожидать ввода-вывода для более чем одного файла или канала, вы выполняете асинхронные запросы ввода-вывода для каждого из этих файлов, а затем ждете завершения указанных запросов. Что-то вроде этого (не проверено):
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
в линуксе
Еще более продвинутая техника Порты завершения ввода / вывода. Это позволяет иметь пул потоков, обрабатывающий множество асинхронных операций ввода-вывода. Обычно используемый в веб-серверах и тому подобное, вероятно, излишний для вашего случая.
Всплывающее STARTUPINFO
как показывает ОП отлично работает если Вы не пропустите CREATE_NO_WINDOW
аргумент в dwFlags
аргумент CreateProcess
.