Непонятки с CreateProcess
От: Selestin  
Дата: 09.07.10 21:45
Оценка:
Добрый день, спрашиваю тут, т.к. сам решения вопроса не вижу.

Задача:
Запустить через критпроцесс консольное приложение, перенаправив потоки ввода вывода в родительскую программу, далее кинуть в поток ввода число, далее прочитать поток вывода.

Вроде задача не сложная, делаем так:
Переменные:
STARTUPINFO si;
PROCESS_INFORMATION pi;
SECURITY_DESCRIPTOR sd;
SECURITY_ATTRIBUTES sa;
LPSECURITY_ATTRIBUTES lpsa = NULL;

Объявим хендлы:
HANDLE hStdOutLocal;
HANDLE hStdOutRemote;
HANDLE hStdInLocal;
HANDLE hStdInRemote;

Инициализация дескриптора:
InitializeSecurityDescriptor(&sd,SECURITY_DESCRIPTOR_REVISION);
SetSecurityDescriptorDacl(&sd, true, NULL, false);

Инициализация атрибутов дискриптора:
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.bInheritHandle = true;
sa.lpSecurityDescriptor = &sd;
lpsa = &sa;

Создание каналов передачи данных:
CreatePipe(&hStdOutLocal, &hStdOutRemote, lpsa,25000);
CreatePipe(&hStdInRemote, &hStdInLocal, lpsa,25000);

Заполним структуру запуска:
memset(&si, 0, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
si.dwFlags = STARTF_USESHOWWINDOW |STARTF_USESTDHANDLES;
si.wShowWindow = SW_HIDE;
si.hStdOutput = hStdOutRemote;
si.hStdInput = hStdInRemote;

Ну и собственно критпроцесс:
if(!CreateProcess(NULL,filename, NULL, NULL, TRUE, 0, 0, 0, &si, &pi))
{
dialog_send("Could not open file (error %d)\r\n", GetLastError());
return;
}

Работает нормально, однако запуская приложение написанное на Assembler'е я получаю Краш дочерней проги без каких либо объяснений, ошибку критпроцесс не возвращает, опытным путем выяснил, что без использования перенаправления stdin/stdout(STARTF_USESTDHANDLES) запускается нормально.

В чем проблема непонятно, может есть какие-то ньюансы работы потоковых перенаправлений с ASM программами?

После детальных исследований было выявлено место краша:
00401063 mov bl,byte ptr [esi]
Дизасм запускаемой ассемблеровской проги прилагается:
http://paste.org/pastebin/view/20366

Похоже ошибка доступа к памяти гдето в дочерней проге.

С уважением, Александр.
Re: Непонятки с CreateProcess
От: Jolly Roger  
Дата: 10.07.10 06:40
Оценка:
Здравствуйте, Selestin, Вы писали:


S>Дизасм запускаемой ассемблеровской проги прилагается:

S>http://paste.org/pastebin/view/20366

Немного смущает наличие вызова AllocConsole. Оно что, собирается без опции /SUBSYSTEM:CONSOLE? Не уверен, что в этом случае поля si.hStdOutput и si.hStdInput будут использованы, хотя не проверял. И ещё, вряд-ли стоит наследовать оба конца пайпов, лучше, по-моему, воспользоваться DuplicateHandle для получения ненаследуемых хёндлов.

По сабжу — почему бы не подключиться отладчиком, воспользовавшись, к примеру, CREATE_SUSPENDED или даже просто sleep'ом?
"Нормальные герои всегда идут в обход!"
Re[2]: Непонятки с CreateProcess
От: Selestin  
Дата: 10.07.10 10:04
Оценка:
Здравствуйте, Jolly Roger, Вы писали:

JR>Здравствуйте, Selestin, Вы писали:


AllocConsole вызывается в асм проге для инициализации консоли, компилится она masm32 вроде.
Вот кусок кода:
invoke AllocConsole
invoke GetStdHandle,-11
mov stdout,eax
invoke GetStdHandle,STD_INPUT_HANDLE
mov stdin,eax
Вроде как-то так работает.

Про дубликат хендл пишут, что копировать ввод вывод можно только в пределах процесса:
Консольный ввод данных (Console input):
Дескриптор возвращается функцией CreateFile, когда установлен CONIN$, или функцией GetStdHandle, когда установлен флажок STD_INPUT_HANDLE. Консольные дескрипторы могут быть дублированы для использования только в том же самом процессе.

Экранный буфер консоли (Console screen buffer):
Дескриптор возвращается функцией CreateFile, когда установлен CONOUT$, или функцией GetStdHandle, когда установлен флажок STD_OUTPUT_HANDLE. Консольные дескрипторы могут быть продублированы для использования только в том же самом процессе.

Дебаггером попробую, спасибо.
Re[3]: Непонятки с CreateProcess
От: Jolly Roger  
Дата: 10.07.10 14:08
Оценка:
Здравствуйте, Selestin, Вы писали:

S>AllocConsole вызывается в асм проге для инициализации консоли, компилится она masm32 вроде.


С masm32 поставляется линкер Link.exe, который знает опцию /SUBSYSTEM:CONSOLE. Посмотрите в папке masm32\bin, там должен быть файл BUILDC.BAT. Я просто далеко не уверен, что унаследованные хёндлы будут использованы для консоли, созданной вызовом AllocConsole.

S>Про дубликат хендл пишут, что копировать ввод вывод можно только в пределах процесса:

S>Консольный ввод данных (Console input):
S>Дескриптор возвращается функцией CreateFile, когда установлен CONIN$, или функцией GetStdHandle, когда установлен флажок STD_INPUT_HANDLE. Консольные дескрипторы могут быть дублированы для использования только в том же самом процессе.

Ну вот и оставьте себе ненаследуемые продублированные "концы", а наследуемые закройте. В запускаемом приложении должно быть по одному хёндлу из каждой пара, зачем ему все четыре?
"Нормальные герои всегда идут в обход!"
Re[4]: Непонятки с CreateProcess
От: Selestin  
Дата: 10.07.10 18:11
Оценка:
Здравствуйте, Jolly Roger, Вы писали:


JR>С masm32 поставляется линкер Link.exe, который знает опцию /SUBSYSTEM:CONSOLE. Посмотрите в папке masm32\bin, там должен быть файл BUILDC.BAT. Я просто далеко не уверен, что унаследованные хёндлы будут использованы для консоли, созданной вызовом AllocConsole.

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

JR>Ну вот и оставьте себе ненаследуемые продублированные "концы", а наследуемые закройте. В запускаемом приложении должно быть по одному хёндлу из каждой пара, зачем ему все четыре?

Теперь понял, спасибо.
Re: Непонятки с CreateProcess
От: Selestin  
Дата: 12.07.10 20:05
Оценка:
Всетаки не получилось сделать через пайпы, из-за того что дочерняя прога вызывает AllocConsole.
Появился вариант сделать через AttachConsole, темболее что хендл дочернего процесса я знаю, т.к. сам его создаю.

Функция
WriteFile(GetStdHandle(STD_OUTPUT_HANDLE),"1\r\n ",2,&BytesBuffer,NULL);
Работает на ура, буфер вывода легко читаем и записываем.

Проблемы возникли с STD_INPUT_HANDLE, пробовал сделать WriteFile туда, ничего не происходит, однако через пайпы этой функцией отправляло все нормально, может нужно эмулировать нажатие enter? Хотя мне кажется врядли, мож я что не так делаю?
Re[2]: Непонятки с CreateProcess
От: Selestin  
Дата: 13.07.10 09:38
Оценка:
S>Проблемы возникли с STD_INPUT_HANDLE, пробовал сделать WriteFile туда, ничего не происходит, однако через пайпы этой функцией отправляло все нормально, может нужно эмулировать нажатие enter? Хотя мне кажется врядли, мож я что не так делаю?

Похоже что stdin открыт только для чтения, но какже тогда работает клавиатура? Она же записывает туда как-то?
Пробовал открывать для записи так:
hCrt = _open_osfhandle((long) GetStdHandle(STD_INPUT_HANDLE), _O_TEXT);
hf = _fdopen( hCrt, "w" );
*stdin = *hf;

Не работает...

В чем может быть трабл?
Re[2]: Непонятки с CreateProcess
От: quodum  
Дата: 13.07.10 11:03
Оценка:
Здравствуйте, Selestin, Вы писали:

S>Проблемы возникли с STD_INPUT_HANDLE, пробовал сделать WriteFile туда, ничего не происходит, однако через пайпы этой функцией отправляло все нормально, может нужно эмулировать нажатие enter? Хотя мне кажется врядли, мож я что не так делаю?


WriteConsoleInput
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.