WaitForInputIdle

Тема в разделе "WASM.WIN32", создана пользователем Fess exe, 5 июн 2005.

  1. Fess exe

    Fess exe New Member

    Публикаций:
    0
    Регистрация:
    24 май 2004
    Сообщения:
    19
    Адрес:
    Russia
    Какие-то глюки с этой функцией. В MSDN написано "WaitForInputIdle function waits until the specified process is waiting for user input with no input pending, or until the time-out interval has elapsed". То есть я так понимаю, что вприведённом ниже фрагменте кода WaitForInputIdle должна возвращать 0, а она возвращает WAIT_FAILED, то есть -1(то есть ошибка в том, что "не найден указанный модуль"). Собственно имеется два вопроса:

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

    2) Если это не сделать с помощью WaitForInputIdle, то можно ли как-то по-другому(ведь cmd.exe как-то умеет это делать).

    Вот код:


    Код (Text):
    1. void main()
    2. {
    3.     PROCESS_INFORMATION pinfo={0,0,0,0};
    4.     SECURITY_ATTRIBUTES sat;
    5.     sat.nLength=sizeof(sat);
    6.     sat.lpSecurityDescriptor=NULL;
    7.     sat.bInheritHandle=TRUE;
    8.  
    9.     STARTUPINFO st;
    10.     st.cb=sizeof(st);
    11.     GetStartupInfo(&st);
    12.     st.dwFlags=STARTF_USESHOWWINDOW;
    13.     st.wShowWindow=SW_SHOWNORMAL;
    14.  
    15.     CreateProcess(NULL,"tcs.exe",&sat,NULL,TRUE,NULL,NULL,NULL,&st,&pinfo);
    16.  
    17.     DWORD f=WaitForInputIdle(pinfo.hProcess,10000);
    18.     if(f==WAIT_TIMEOUT)
    19.         MessageBox(NULL,"WAIT_TIMEOUT",NULL,MB_OK);
    20.     else if(f==WAIT_FAILED)
    21.     {
    22.         errmsg();
    23.         MessageBox(NULL,"WAIT_FAILED",NULL,MB_OK);
    24.     }
    25.     else
    26.     {
    27.         MessageBox(NULL,"0",NULL,MB_OK);
    28.     }
    29. }


    tcs.exe ::
    Код (Text):
    1.  
    2. void main()
    3. {
    4.     int a;
    5.     cin>>a;
    6. }
     
  2. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    Fess exe

    Приложение, которое вызывает WaitForInputIdle, не может быть консольным.
     
  3. Fess exe

    Fess exe New Member

    Публикаций:
    0
    Регистрация:
    24 май 2004
    Сообщения:
    19
    Адрес:
    Russia
    Даже если это верно, то это ничего не меняет. Можно заменить main на WinMain и результат не меняется(только что проверил).
     
  4. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    Что значит
    ? Не доверяете? Правильно :)





    CUI от GUI отличается не названием main'а, а флагом в заголовке экзешника! Линкеру нужно указать /SUBSYSTEM:CONSOLE вместо /SUBSYSTEM:WINDOWS. Короче, чтоб не мучаться с настройками проекта, создайте новый и укажите Win32 Application, а не Win32 Console Application. Это справедливо для VC++ 6. Это раз!



    У GUI-приложения должна быть очередь сообщений. Не поленитесь создать окно, хоть скрытое. Это два!
     
  5. Fess exe

    Fess exe New Member

    Публикаций:
    0
    Регистрация:
    24 май 2004
    Сообщения:
    19
    Адрес:
    Russia
    "создайте новый и укажите Win32 Application, а не Win32 Console Application" - Я так и сделал, просто неверно выразился. Короче НЕ РАБОТАЕТ в любом случае!
     
  6. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    Fess exe

    А перечитать моё предыдущее сообщение, но на этот раз внимательно?
     
  7. yureckor

    yureckor New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2004
    Сообщения:
    494
    Адрес:
    Russia
    2 Quantum

    я ожидаю окончания распаковки sfx RAR архива (который консольный)
    Код (Text):
    1. inv_win WaitForSingleObject, [prinfo.hProcess], INFINITE


    все работает.
     
  8. q_q

    q_q New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2003
    Сообщения:
    1.706
    yureckor

    Речь о WaitForInputIdle. :derisive:



    Quantum

    Приложение, которое вызывает WaitForInputIdle, не может быть консольным.

    Откуда информация?
     
  9. bogrus

    bogrus Active Member

    Публикаций:
    0
    Регистрация:
    24 окт 2003
    Сообщения:
    1.338
    Адрес:
    ukraine
    WaitForInputIdle находится в user32.dll, который связан с gdi32.dll, а тот создает очередь сообщений при своей инициализации, т.ч. работать должно независимо от CUI\GUI
     
  10. alpet

    alpet Александр

    Публикаций:
    0
    Регистрация:
    21 сен 2004
    Сообщения:
    1.221
    Адрес:
    Russia
    Очередь сообщений по видимому должна быть у приложения tcs.exe, поскольку процессу вызывающему WaitForInputIdle интересно то, когда все потоки запущенного процесс им процесса окажутся с пустыми очередями сообщений. Если потоков с циклами и соответственно очередями сообщений у запущенного процесса нет (например у консольного приложения), функция и возвернет ошибку. Другое дело что использовать эту функцию в консольном приложении можно также как и в GUI-шном.
     
  11. bogrus

    bogrus Active Member

    Публикаций:
    0
    Регистрация:
    24 окт 2003
    Сообщения:
    1.338
    Адрес:
    ukraine




    У меня на w2k очередь быть не обязана, это легко проверяется, вот 2 консольных приложения



    1. target.exe кроме Sleep,5000 ничего не делает, очереди у неё нет

    2. create.exe запускает target.exe и вызывает WaitForInputIdle (очередь есть)



    Т.к. консольное окно create.exe висит 5 секунд, я делаю вывод что WaitForInputIdle работает (хотя по отладчику не скажешь, странно...)



    [​IMG] 331135518__cui.zip
     
  12. alpet

    alpet Александр

    Публикаций:
    0
    Регистрация:
    21 сен 2004
    Сообщения:
    1.221
    Адрес:
    Russia
    WinXP,SP2.



    У меня возвращается ошибка, при запуске консольного приложения "C:\Windows\System32\cmd.exe". Таймаут установлен в 1000, но функция не ждет, а возвращает ошибку сразу. Видимо Sleep как-то обманывает эту функцию. Но самое интересное - GetLastError возвращает значение LastError бывшее до вызова WaitForInputIdle, например ноль. Так-что зря советуют использовать GetLastError в MSDN.


    Код (Text):
    1.  
    2.  SetLastError (0);
    3.  DWORD res = WaitForInputIdle (hProcess, 1000);
    4.  if ((DWORD)-1 == res)
    5.  {
    6.     int err = GetLastError ();
    7.     printf ("Error calling WFI, %d ", err);
    8.  }
    9.  
     
  13. q_q

    q_q New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2003
    Сообщения:
    1.706
    bogrus

    я делаю вывод что WaitForInputIdle работает

    В чем выражается ее работа?

    Она возвращает WAIT_FAILED, а последующий GetLastError возвращает NO_ERROR.

    В документации, imho, четко написано "If ... process is a console application or does not have a message queue, WaitForInputIdle returns immediately".



    Т.е. ответ на первый вопрос ветки "ни как".

    Остается второй вопрос: "как родительский процесс может определить, что ребенок ждет ввода с консоли/stdin".
     
  14. bogrus

    bogrus Active Member

    Публикаций:
    0
    Регистрация:
    24 окт 2003
    Сообщения:
    1.338
    Адрес:
    ukraine
    q_q точно, согласен, это меня ввело в заблуждение то, что консольное окно target.exe имело имя родительского процесса create.exe
     
  15. yureckor

    yureckor New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2004
    Сообщения:
    494
    Адрес:
    Russia
    q_q

    просмотрел :)

    Fess exe

    я делал так (мне необходимо получить данные со скрытой консоли cmd.exe, запущенной на чужом окне)
    Код (Text):
    1. otprav_ret proc lp_komu:DWORD
    2. Local m1:strukt_memory
    3. Local so:OVERLAPPED
    4. Local l1_lc:DWORD, l2_lc:DWORD, l3_lc:DWORD
    5. pushad
    6. invoke psh_sel_akt
    7.  invoke fill_memory, ADDR m1, SIZEOF strukt_memory, 0
    8.  invoke create_memory, ADDR m1, 32000
    9.  invoke fill_memory, ADDR so, SIZEOF OVERLAPPED, 0
    10.  mv [so.loffset], 0
    11.  
    12.  invoke sleep, 100
    13.  
    14.  mov ecx, 20
    15.  @@1:
    16.   dec ecx
    17.   jz @@2
    18.   invoke sleep, 200
    19.   inva_win PeekNamedPipe, [hReadPipe2], [m1.mem], [m1.len], ADDR l1_lc, ADDR l2_lc, ADDR l3_lc
    20.   CP eax, 0, Z, @@1
    21.   mov eax, [l1_lc]
    22.  CP eax, 0, Z, @@1
    23.  CP eax, [l2_lc], C, @@1
    24.  inv_win ReadFile, [hReadPipe2], [m1.mem], [m1.len], ADDR l1_lc, ADDR so
    25.  @@2:
    26.  invoke vipolni_far_kom, [m1.mem], [lp_komu], tx("command_ret")
    27.  invoke close_memory, ADDR m1
    28.  
    29. invoke po_sel_akt
    30. popad
    31. ret
    32. otprav_ret endp
    33.  


    когда создавал cmd.exe, то его ввод/вывод перенаправил на потоки (pipe). Но это все равно не лучший выход, т.к. например запуск на удаленной машине команды dir может привести к тому, что проверка сработает когда выведено только часть информации.
     
  16. Fess exe

    Fess exe New Member

    Публикаций:
    0
    Регистрация:
    24 май 2004
    Сообщения:
    19
    Адрес:
    Russia
    yureckor

    Если я правильно понял(а возможно и нет, ибо не совсем ясно что есть hReadPipe2, и др. т.е. хотелось бы видеть описание всех функций и переменных, иначе не понятно что для чего), то с помощью PeekNamedPipe узнаётся, есть ли чего-нибудь в потоке вывода программы и если там пусто, то считается, что программа ждёт ввода. Тут есть ещё одна проблема. Программа может чего-нибудь вывести, а потом задуматься надолго, а пока она будет думать, родительский прецесс считает из пайпа и сможет пытаться посылать данные на ввод дочернему, тогда как тот в то же время может выйти из задумчивости. Предполагается, что тот, кто пишет процесс-родитель, не знает ничего о процессе-наследнике.
     
  17. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    q_q



    Из борландовской справки:

    "The WaitForInputIdle function only works with GUI applications. If a console application calls the function, it returns immediately, with no wait."



    Fess exe



    Что именно умеет делать cmd.exe? Уточните.
     
  18. Fess exe

    Fess exe New Member

    Публикаций:
    0
    Регистрация:
    24 май 2004
    Сообщения:
    19
    Адрес:
    Russia
    Quantum

    cmd.exe ничего не знает о том процессе, который запускает, но корректно пишет и читает из его потоков ввода и вывода и не ошибается из-за "задумчивости"(см. мой пост чуть выше) программ.
     
  19. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    Fess exe

    Это не CMD пишет/читает, а сам процесс. Просто он наследует консоль.



    Я не понял суть проблемы с "задумчивостью". Пайп имеет буффер, в который один процесс помещает данные (в любом количестве) и они там будут храниться пока второй процесс их не прочитает или пока пайп кто-то не разрушит.
     
  20. Fess exe

    Fess exe New Member

    Публикаций:
    0
    Регистрация:
    24 май 2004
    Сообщения:
    19
    Адрес:
    Russia
    Quantum

    "Это не CMD пишет/читает, а сам процесс. Просто он наследует консоль" - поясните, если можно.

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