C++, зависает DOS4GW приложение, которому перенаправлен ввод
Типа
my_dos4gw_prog.exe <file.in
работает
type file.in | my_dos4gw_prog.exe
Да так тоже работает
--------------------------------
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" от которой он зависает
![](/images/graemlins/frown.gif)
![](/images/graemlins/shocked.gif)
![](/images/graemlins/shocked.gif)
![](/images/graemlins/shocked.gif)
![](/images/graemlins/shocked.gif)
![](/images/graemlins/shocked.gif)
![](/images/graemlins/shocked.gif)
![](/images/graemlins/shocked.gif)
перейди на Линукс, скомпилируй все под линуксом...
ну это ж пиздец... :/
Имхо тебе стОит копать в сторону параметров самой CreateProcess. Например, там есть замечательный флажок CREATE_SEPARATE_WOW_VDM. Ну и вообще посмотри на неё внимательно - нафига ты передаёшь bInheritHandles == TRUE, например.
А TRUE передаю, чтобы он смог наследовать перенаправленный поток ввода вродебы, по крайнем мере в мсдн и во всех примерах так делают.
Вобщем всем спасибо, видимо надо будет чтото другое придумывать
Это был способ номер один, который был попробован. С ним результатов ровно столькоже, хотя ничего извратного в том, чтобы дать дочернему процессу унаследовать консоль, поправьте меня, нет.
если win32 консольная прога работает, а dos не работает - значит мс накосячила в эмуляторе.
вот кусочек моего кода, с полным перехватом 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);
DuplicateHandle(GetCurrentProcess, HandleStdInRead,смысл в этой магической операции только проставление наследуемости? или есть ещё какой-то эффект?
GetCurrentProcess, @HandleStdInTmp,
0, true, DUPLICATE_SAME_ACCESS);
CloseHandle(HandleStdInRead);
man dup
![](/images/graemlins/smile.gif)
![](/images/graemlins/frown.gif)
Но в данном примере я принципиальных различий не вижу, через CREAT_NEW_CONSOLE + SA.bInheritHandle:= TRUE + передачу хэндлов через startup information уже пробовал, результат тот же даже хуже.
Смотреть что там в stderr и ждать окончания работы приложения смысла нет, поскольку 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 - конец
В чем может быть проблема?
Может для запуска таких приложений нужно както хитрить, устанавливать переменные окружения или чтонибудь такое?