Рекурсивное создание процесса

Тема в разделе "WASM.WIN32", создана пользователем wild89, 27 мар 2010.

  1. wild89

    wild89 New Member

    Публикаций:
    0
    Регистрация:
    27 мар 2010
    Сообщения:
    15
    У меня Windows XP Professional SP3.
     
  2. KeSqueer

    KeSqueer Сергей

    Публикаций:
    0
    Регистрация:
    19 июл 2007
    Сообщения:
    1.183
    Адрес:
    Москва
    l_inc
     
  3. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    KeSqueer
    Не понимаю, причём здесь эти поля. Например, cmd в них передаёт нули.
    Правда, передача значения хэндла у него никак не связана с PROC_THREAD_ATTRIBUTE_EXTENDED_FLAGS, как я думал в предыдущем посте, а выполняется за счёт того, что он предварительно сам себе делает SetStdHandle. Соответственно значение hStdOutput из его RTL_USER_PROCESS_PARAMETERS остаётся таким же в АП дочернего процесса. Почему его хэндл printf'у нравится, а хэндл wild89 нет, всё ещё неясно. :)
     
  4. KeSqueer

    KeSqueer Сергей

    Публикаций:
    0
    Регистрация:
    19 июл 2007
    Сообщения:
    1.183
    Адрес:
    Москва
    l_inc
    При том, что функция CRT для создания процесса (_spanw) использует эти поля для передачи хэндлов.
    Видимо cmd не использует такой "внутреннеCRTшный" способ передачи.
    Все оказалось банально - просто после printf нужно сделать fflush(stdout), т.к. CRT буферизует вывод.
     
  5. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    KeSqueer
    Ну не настолько. :) Про буферизацию в зависимости от типа хэндла я в курсе. Проблема в том, что, если cmd запускает процесс, то fflush не обязателен.
     
  6. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    P.S. Собственно, вопрос в том, почему.
     
  7. KeSqueer

    KeSqueer Сергей

    Публикаций:
    0
    Регистрация:
    19 июл 2007
    Сообщения:
    1.183
    Адрес:
    Москва
    l_inc
    Странно, теперь такой код выполняется как надо (т.е. вывод в файл идёт):

    Test.c:
    Код (Text):
    1. #include <windows.h>
    2. #include <stdio.h>
    3. #include <tchar.h>
    4.  
    5. int main(void)
    6. {
    7.     BOOL bRet;
    8.     STARTUPINFO si = {sizeof(STARTUPINFO)};
    9.     PROCESS_INFORMATION pi = {0};
    10.     SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE};
    11.  
    12.     si.dwFlags = STARTF_USESTDHANDLES;
    13.     si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
    14.     si.hStdOutput = CreateFile(TEXT("out.txt"), GENERIC_WRITE, FILE_SHARE_READ, &sa,
    15.         CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    16.  
    17.     bRet = CreateProcess(TEXT("Target.exe"), NULL, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi);
    18.  
    19.     WaitForSingleObject(pi.hProcess, INFINITE);
    20.     CloseHandle(pi.hProcess);
    21.     CloseHandle(pi.hThread);
    22.     CloseHandle(si.hStdOutput);
    23.     return 0;
    24. }
    Target.c:
    Код (Text):
    1. #include <windows.h>
    2. #include <stdio.h>
    3. #include <tchar.h>
    4.  
    5. int main(void)
    6. {
    7.     _tprintf(__T("Text"));
    8.     Sleep(INFINITE);
    9.     return 0;
    10. }
    P.S. В настройках проекта пришлось поменять рабочую папку, чтобы не указывать полный путь (либо относительно папки с файлом проекта) в вызове CreateProcess.
     
  8. KeSqueer

    KeSqueer Сергей

    Публикаций:
    0
    Регистрация:
    19 июл 2007
    Сообщения:
    1.183
    Адрес:
    Москва
    P.S.
    Вывод идет после завершения дочернего процесса.
     
  9. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    KeSqueer
    ЛОЛ! Всё оказалось действительно банально. :) Сброс буферов на диск выполняется CRT после return. Если выполнить CloseHandle в дочернем процессе, то естественно, что к моменту сброса буферов писать будет уже некуда.
    Огромное спасибо за рабочий вариант. Я уж думал, магия cmd. :)
    wild89
    Рабочий кошерный вариант с унарным деревом на семафоре:
    Код (Text):
    1. int main(void)
    2. {
    3.     BOOL bMainProcess = FALSE;
    4.     STARTUPINFO si = {0};
    5.     PROCESS_INFORMATION pi;
    6.     SECURITY_ATTRIBUTES sa;
    7.     TCHAR strBuf[MAX_PATH];
    8.  
    9.     sa.nLength=sizeof(sa);
    10.     sa.lpSecurityDescriptor = NULL;
    11.     sa.bInheritHandle= TRUE;
    12.     HANDLE f;
    13.     HANDLE hSem = CreateSemaphore(NULL, PROCESS_COUNT, PROCESS_COUNT, TEXT("MySem"));
    14.     if (bMainProcess = (GetLastError() != ERROR_ALREADY_EXISTS))
    15.         f = CreateFile(TEXT("out.txt"),GENERIC_WRITE, FILE_SHARE_READ ,&sa,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0);
    16.     else
    17.         f = GetStdHandle(STD_OUTPUT_HANDLE);
    18.  
    19.     si.cb               = sizeof(si);
    20.     si.dwFlags          = STARTF_USESTDHANDLES;
    21.     si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
    22.     si.hStdOutput = f;
    23.     si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
    24.  
    25.     if(WAIT_OBJECT_0 == WaitForSingleObject(hSem, 0))
    26.     {
    27.         GetModuleFileName(NULL,strBuf,MAX_PATH);
    28.         CreateProcess(strBuf, NULL, NULL, NULL, TRUE,0, NULL, NULL, &si, &pi);
    29.         _tprintf(TEXT("Waiting for child...\n"));
    30.         WaitForSingleObject(pi.hProcess,INFINITE);
    31.         CloseHandle(pi.hProcess);
    32.         CloseHandle(pi.hThread);
    33.     } else
    34.         _tprintf(TEXT("Last level reached!\n"));
    35.     CloseHandle(hSem);
    36.  
    37.     if (bMainProcess)
    38.         CloseHandle(f);         //имеет чисто символическое значение для очистки совести
    39.     return 0;
    40. }
    Из-за асинхронного характера работы CRT с некосносльными хэндлами вывод в файл идёт в порядке завершения работы процессов, а не в порядке их запуска.
     
  10. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    P.S. "Некосносльные" следует читать, как "неконсольные". :)
     
  11. wild89

    wild89 New Member

    Публикаций:
    0
    Регистрация:
    27 мар 2010
    Сообщения:
    15
    Большое Вам человеческое спасибо!
    Очень вам благодарен.
     
  12. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    P.P.S. хотя у ТС код... мягко говоря, оставляет желать лучшего, вывод в файл в нём таки работает... если оставить код без изменений. Разве что в структуру pi у него каждый раз попадает подходящий хэндл: только в этом случае файл мог оставаться пустым.
    У меня же файл был действительно пуст, т.к. я перед тестом исправил ошибки в коде ТС. :) После чего открывался файл у меня одноразово, а закрывался каждый раз "правильный" хэндл. :)