KeSqueer Не понимаю, причём здесь эти поля. Например, cmd в них передаёт нули. Правда, передача значения хэндла у него никак не связана с PROC_THREAD_ATTRIBUTE_EXTENDED_FLAGS, как я думал в предыдущем посте, а выполняется за счёт того, что он предварительно сам себе делает SetStdHandle. Соответственно значение hStdOutput из его RTL_USER_PROCESS_PARAMETERS остаётся таким же в АП дочернего процесса. Почему его хэндл printf'у нравится, а хэндл wild89 нет, всё ещё неясно.
l_inc При том, что функция CRT для создания процесса (_spanw) использует эти поля для передачи хэндлов. Видимо cmd не использует такой "внутреннеCRTшный" способ передачи. Все оказалось банально - просто после printf нужно сделать fflush(stdout), т.к. CRT буферизует вывод.
KeSqueer Ну не настолько. Про буферизацию в зависимости от типа хэндла я в курсе. Проблема в том, что, если cmd запускает процесс, то fflush не обязателен.
l_inc Странно, теперь такой код выполняется как надо (т.е. вывод в файл идёт): Test.c: Код (Text): #include <windows.h> #include <stdio.h> #include <tchar.h> int main(void) { BOOL bRet; STARTUPINFO si = {sizeof(STARTUPINFO)}; PROCESS_INFORMATION pi = {0}; SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE}; si.dwFlags = STARTF_USESTDHANDLES; si.hStdInput = GetStdHandle(STD_INPUT_HANDLE); si.hStdOutput = CreateFile(TEXT("out.txt"), GENERIC_WRITE, FILE_SHARE_READ, &sa, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); bRet = CreateProcess(TEXT("Target.exe"), NULL, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi); WaitForSingleObject(pi.hProcess, INFINITE); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); CloseHandle(si.hStdOutput); return 0; } Target.c: Код (Text): #include <windows.h> #include <stdio.h> #include <tchar.h> int main(void) { _tprintf(__T("Text")); Sleep(INFINITE); return 0; } P.S. В настройках проекта пришлось поменять рабочую папку, чтобы не указывать полный путь (либо относительно папки с файлом проекта) в вызове CreateProcess.
KeSqueer ЛОЛ! Всё оказалось действительно банально. Сброс буферов на диск выполняется CRT после return. Если выполнить CloseHandle в дочернем процессе, то естественно, что к моменту сброса буферов писать будет уже некуда. Огромное спасибо за рабочий вариант. Я уж думал, магия cmd. wild89 Рабочий кошерный вариант с унарным деревом на семафоре: Код (Text): int main(void) { BOOL bMainProcess = FALSE; STARTUPINFO si = {0}; PROCESS_INFORMATION pi; SECURITY_ATTRIBUTES sa; TCHAR strBuf[MAX_PATH]; sa.nLength=sizeof(sa); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle= TRUE; HANDLE f; HANDLE hSem = CreateSemaphore(NULL, PROCESS_COUNT, PROCESS_COUNT, TEXT("MySem")); if (bMainProcess = (GetLastError() != ERROR_ALREADY_EXISTS)) f = CreateFile(TEXT("out.txt"),GENERIC_WRITE, FILE_SHARE_READ ,&sa,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0); else f = GetStdHandle(STD_OUTPUT_HANDLE); si.cb = sizeof(si); si.dwFlags = STARTF_USESTDHANDLES; si.hStdInput = GetStdHandle(STD_INPUT_HANDLE); si.hStdOutput = f; si.hStdError = GetStdHandle(STD_ERROR_HANDLE); if(WAIT_OBJECT_0 == WaitForSingleObject(hSem, 0)) { GetModuleFileName(NULL,strBuf,MAX_PATH); CreateProcess(strBuf, NULL, NULL, NULL, TRUE,0, NULL, NULL, &si, &pi); _tprintf(TEXT("Waiting for child...\n")); WaitForSingleObject(pi.hProcess,INFINITE); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); } else _tprintf(TEXT("Last level reached!\n")); CloseHandle(hSem); if (bMainProcess) CloseHandle(f); //имеет чисто символическое значение для очистки совести return 0; } Из-за асинхронного характера работы CRT с некосносльными хэндлами вывод в файл идёт в порядке завершения работы процессов, а не в порядке их запуска.
P.P.S. хотя у ТС код... мягко говоря, оставляет желать лучшего, вывод в файл в нём таки работает... если оставить код без изменений. Разве что в структуру pi у него каждый раз попадает подходящий хэндл: только в этом случае файл мог оставаться пустым. У меня же файл был действительно пуст, т.к. я перед тестом исправил ошибки в коде ТС. После чего открывался файл у меня одноразово, а закрывался каждый раз "правильный" хэндл.