C++, зависает DOS4GW приложение, которому перенаправлен ввод

vertyal17

Столкнулся с проблемой.
Необходимо из графического приложения запустить консольное, работающее с DOS4GW, и перенаправить ему стандартный поток ввода.
Делаю почти в соответствии с MSDN, создаю консоль, создаю пайп, заменяю STD_INPUT_HANDLE на выход пайпа, запускаю приложение с помощью CreateProcess.
Приложение зависает, успев показать
DOS/4GW Protected Mode Run-time Version 1.97
Copyright (c) Rational Systems, Inc. 1990-1994
При этом, если запускать другое приложение (например cmd.exe) то все работает, cmd начинает переваривать то, что ему пихается через pipe, выполняет различные команды и т.п. Но при попытке из cmd запустить мое dos4gw приложение, он опять зависает.
В то же время, если не перенаправлять ввод, то Dos4GW приложение запускается и работает (хотя ксожалению никаких команд ему из графического приложения передать не получается).
МОжно даже перенаправить stdout и stderr, приложение все равно приложение будет запускаться. Но как только заменяю stdin - конец
В чем может быть проблема?
Может для запуска таких приложений нужно както хитрить, устанавливать переменные окружения или чтонибудь такое?

vertyal17

Если например в какомнибудь фаре, перенаправить этому приложению входной поток на файл, то оно запускается, и нормально воспринимает входной поток из файла.
Типа
my_dos4gw_prog.exe <file.in
работает

Dasar

так работает?

type file.in | my_dos4gw_prog.exe

vertyal17

Да так тоже работает

vertyal17

Порезанная для простоты понимания в некоторых местах моя программа
--------------------------------
STARTUPINFO si;
SECURITY_ATTRIBUTES sa;
SECURITY_DESCRIPTOR sd;

HANDLE newstdin, newstdout;
InitializeSecurityDescriptor(&sd,SECURITY_DESCRIPTOR_REVISION);
SetSecurityDescriptorDacl(&sd, true, NULL, false);
sa.lpSecurityDescriptor = NULL; //&sd; // Probably we should use NULL here
sa.nLength=sizeof(SECURITY_ATTRIBUTES);
sa.bInheritHandle=true;
BOOL RetVal = AllocConsole;
if (RetVal==FALSE) {return;};
if (!CreatePipe(&newstdin,&write_stdin,&sa,NULL {return;};
if (!CreatePipe(&read_stdout,&newstdout,&sa,NULL {return;};
SetHandleInformation( write_stdin, HANDLE_FLAG_INHERIT, 0);
SetHandleInformation( read_stdout, HANDLE_FLAG_INHERIT, 0);
GetStartupInfo(&si); //ñîçäàåì startupinfo äë_ äî_åðíåãî ïðîRåññà
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_SHOWNORMAL;
/*!*/SetStdHandle( STD_INPUT_HANDLE, newstdin);
if (!CreateProcess(NULL,"E303BT10.EXE",NULL,NULL,TRUE,/*CREATE_NEW_CONSOLE/**/NULL/**/,NULL,NULL,&si,&process_information
{
return;
}
CloseHandle(newstdin);
CloseHandle(newstdout);
FreeConsole;
---------------------------------------
Если убрать помеченное /*!*/ то программа запускается.
Если вместо E303BT10.EXE, запустить cmd.exe, то он запускается, и переваривает все что ему передавать по pipe. За исключением строки "E303BT10.EXE\n" от которой он зависает

Werdna

вот ведь проблемы у виндузятников...
перейди на Линукс, скомпилируй все под линуксом...
ну это ж пиздец... :/

bleyman

Имхо тебе стОит копать в сторону параметров самой CreateProcess. Например, там есть замечательный флажок CREATE_SEPARATE_WOW_VDM. Ну и вообще посмотри на неё внимательно - нафига ты передаёшь bInheritHandles == TRUE, например.

vertyal17

Среат_Сепарат_Вов_Вдм передавал, не помогло.
А TRUE передаю, чтобы он смог наследовать перенаправленный поток ввода вродебы, по крайнем мере в мсдн и во всех примерах так делают.
Вобщем всем спасибо, видимо надо будет чтото другое придумывать

vall

изврат
а si.hStdInput si.hStdOutput использовать не судьба?
на http://www.ejudge.ru в libreuse это есть

vertyal17

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

vall

а, тебе именно с пайпами нужно? я файлы пепенаправлял.
если win32 консольная прога работает, а dos не работает - значит мс накосячила в эмуляторе.

yolki

Разобрался уже?
вот кусочек моего кода, с полным перехватом stderr, stdout потоков:
правда на Delphi...

HandleStdOut:=FileOpen('c:\stdout.txt',fmOpenReadWrite+fmShareDenyNone);
//
HandleStdErr:=FileOpen('c:\stderr.txt', fmOpenReadWrite+fmShareDenyNone);
//
SA.nLength:= sizeof(SECURITY_ATTRIBUTES);
SA.lpSecurityDescriptor:= nil;
SA.bInheritHandle:= TRUE;
CreatePipe(HandleStdInRead,HandleStdInWrite,@SA,16*1024);
DuplicateHandle(GetCurrentProcess, HandleStdInRead,
GetCurrentProcess, @HandleStdInTmp,
0, true, DUPLICATE_SAME_ACCESS);
CloseHandle(HandleStdInRead);
//
// Запуск процесса компиляции
// --------------------------
FillChar(InfStartProcess, SizeOf(InfStartProcess #0);
InfStartProcess.cb:=SizeOf(InfStartProcess);
InfStartProcess.dwFlags:=STARTF_USESTDHANDLES;
DuplicateHandle(GetCurrentProcess, HandleStdOut, GetCurrentProcess,
@HandleStdOutTmp, 0, true, DUPLICATE_SAME_ACCESS);
DuplicateHandle(GetCurrentProcess, HandleStdErr, GetCurrentProcess,
@HandleStdErrTmp, 0, true, DUPLICATE_SAME_ACCESS);
InfStartProcess.hStdInput:=HandleStdInTmp;
InfStartProcess.hStdOutput:=HandleStdOutTmp;
InfStartProcess.hStdError:=HandleStdErrTmp;
ResCreate:=CreateProcess(nil,
PChar('c:\a.bat'
nil, nil, {false{}true, CREATE_NEW_CONSOLE, nil,
PChar('c:\' InfStartProcess, InfProcess);
CloseHandle(HandleStdOutTmp);
CloseHandle(HandleStdInTmp);
CloseHandle(HandleStdErrTmp);
CloseHandle(InfProcess.hThread);
// Ждём, пока не закончится запущенный экзешник
repeat
Application.ProcessMessages;
ResWait:=WaitForSingleObject(InfProcess.hProcess, 20);
if ResWait=WAIT_FAILED then Break;
until ResWait = WAIT_OBJECT_0;
CloseHandle(HandleStdOut);
CloseHandle(HandleStdErr);
CloseHandle(HandleStdInWrite);
CloseHandle(InfProcess.hProcess);

vall

DuplicateHandle(GetCurrentProcess, HandleStdInRead,
GetCurrentProcess, @HandleStdInTmp,
0, true, DUPLICATE_SAME_ACCESS);
CloseHandle(HandleStdInRead);
смысл в этой магической операции только проставление наследуемости? или есть ещё какой-то эффект?

yolki

не знаю, сделано по аналогии с unix.
man dup

vertyal17

Не я пока не разобрался, и по большому счету, перепробовав много разных возможных ключиков, забил .
Но в данном примере я принципиальных различий не вижу, через CREAT_NEW_CONSOLE + SA.bInheritHandle:= TRUE + передачу хэндлов через startup information уже пробовал, результат тот же даже хуже.
Смотреть что там в stderr и ждать окончания работы приложения смысла нет, поскольку DOS4GW приложение зависает, и корректным образом уже не завершается/выполняется.
Оставить комментарий
Имя или ник:
Комментарий: