У меня есть небольшая программа, которая принимает входные данные и выполняет некоторую предварительную обработку, прежде чем продолжить свою деятельность. (Классический случай «сделайте нас программой; о, мы еще не знаем точный формат данных».) Чтобы этот шаг был более пригодным для сценариев, я решил использовать AWK для этапа предварительной обработки (потому что данные будут табличный характер).
Достаточно фона. Это сводится к тому, что я пытаюсь вызвать GAWK с CreateProcess.
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 для чтения, либо блокироваться бесконечно (в зависимости от их аргументов).
Задача ещё не решена.