Я не могу сделать IO с Gawk, используя функцию WINAPI CreateProcess

У меня есть небольшая программа, которая принимает входные данные и выполняет некоторую предварительную обработку, прежде чем продолжить свою деятельность. (Классический случай «сделайте нас программой; о, мы еще не знаем точный формат данных».) Чтобы этот шаг был более пригодным для сценариев, я решил использовать AWK для этапа предварительной обработки (потому что данные будут табличный характер).

Достаточно фона. Это сводится к тому, что я пытаюсь вызвать GAWK с CreateProcess.

  • Я вполне уверен, что мой GAWK ожидает UTF-8 (то есть, нет Windows «Unicode» / UTF-16, и я вполне уверен, что я кормлю это так).
  • Это GnuWin32-AWK, поэтому он должен знать пути стилей окон.
  • Я также совершенно уверен, что анонимные каналы, которые используются для связи, установлены правильно; Я сделал скрипт test.bat, который работал правильно. Кроме того, я могу читать сообщения об ошибках AWK из входного канала (дочерний выход), если в командной строке есть тип.
  • Единственный выход, который мне удалось получить, был 0A 0D, то есть \ n \ r.
  • Если командная строка в порядке, WaitForSingleObject() возвращает ошибку 259, указывающую на тупик.

РЕДАКТИРОВАТЬ 1: Это упрощенная версия функции. Я сейчас держу основной цикл. В обоих случаях он делает два витка в цикле.

wstring path = L"C:\\MODBUSSINATOR\\awk\\awk.exe";
wstring args = L"C:\\MODBUSSINATOR\\awk\\awk.exe --file=.\\awk\\recipe.awk";
string source = "PERSE PERSE PERSE";
wchar_t argbuff[args.size()+1];   // MSDN says the arg-buff may be modified by client
wcscpy(argbuff,args.c_str());             // so copy args into array
istringstream inpus(source);
ostringstream resus;

DWORD written=0,retcode=0,read=0,readable=0,inpusize=0,resusize=0;
char inpu_buff[1024],resu[1024],*inpu;

SECURITY_ATTRIBUTES cia = {sizeof(SECURITY_ATTRIBUTES),nullptr,true}, coa = cia;
HANDLE oh,ih,cih,coh;
if(!CreatePipe(&cih,&oh,&cia,BUFF_SZ))  //BUFF_SZ = 1024
abort();
if(!CreatePipe(&ih,&coh,&cia,BUFF_SZ))
abort();

PROCESS_INFORMATION procinfo;
STARTUPINFO startinfo;
memset(&procinfo,0,sizeof(PROCESS_INFORMATION)); // The documentation says to do this.
memset(&startinfo,0,sizeof(STARTUPINFO));        // Though I set all the fields exclusively.
startinfo = {
sizeof(STARTUPINFO),nullptr,nullptr,nullptr,0,0,0,0,0,0,0,
STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES,SW_HIDE,0,nullptr,
cih,coh,coh
};

if(!CreateProcess(
path.c_str(),argbuff,nullptr,nullptr,true, 0 // true, handles are inherited
,nullptr,nullptr,&startinfo,&procinfo
))
abort();

while(true){
if(inpusize <= 0){
inpu = inpu_buff;
inpus.get(inpu,1024);
inpusize = inpus.gcount();
if(inpusize){
if(WriteFile(oh,inpu,inpusize,&written,nullptr)){
inpusize -= written;
inpu += written;
}else
abort();
}else
CloseHandle(oh);
}
if(!PeekNamedPipe(ih,nullptr,0,nullptr,&readable,nullptr))
abort();
if(readable > 0){
if(!ReadFile(ih,resu,readable,&read,nullptr))
abort();
resu[read] = '\0';
resus << resu;
}
if(!written && !read)
break;
read = 0,written = 0;
}

CloseHandle(coh);
CloseHandle(cih);
CloseHandle(ih);
if(WaitForSingleObject(procinfo.hProcess,conf.script_to) == WAIT_TIMEOUT)
abort();

cout << "AWK SAYS:" << endl <<
resus.str() << endl;

Перед упрощениями я читал следующую ошибку из канала:

msgstr «awk: fatal: не могу открыть исходный файл`. \ aD ‘».

Теперь файл тестовой летучей мыши будет заблокирован на WaitForSingleObject() функционировать до истечения времени ожидания. Но вывод идет через ОК («PERSE PERSE PERSE»), а AWK по-прежнему ничего не выводит. Я расследую.

Обратите внимание, что точка доступа вокруг кода, вероятно, находится вокруг CreateProcess() функция. Все остальное — ваше нормальное многословие WinAPI.

Мой recipe.awk на данный момент является просто проходным:

BEGIN { print "paskaa" > "paska.txt" ; }
/.*/ { print $0; }
END { exit 999; }

Выше я использую генерацию файла paska.txt, чтобы указать, что скрипт начинает выполняться. Такого никогда не было.

Это был мой equivalant.bat, который работал как положено:

@ECHO OFF
:LOOP
SET VAR=
SET /P VAR=
IF "%VAR%" NEQ "" (
ECHO %VAR%
GOTO :LOOP
)

Пожалуйста, потерпите мою некомпетентность. Мне бы очень понадобился ваш свежий вклад.


РЕДАКТИРОВАТЬ 2: Мне удалось решить проблему,
Мне не хватало этих:

SetHandleInformation(ihh,HANDLE_FLAG_INHERIT,0)
SetHandleInformation(ohh,HANDLE_FLAG_INHERIT,0)

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

Было очень грустно провести полтора рабочих дня с этим.


РЕДАКТИРОВАТЬ 3И как дальнейшая помощь для странных гуглеров там:

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

0

Решение

Задача ещё не решена.

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


По вопросам рекламы [email protected]