Какие-то глюки с этой функцией. В 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): void main() { PROCESS_INFORMATION pinfo={0,0,0,0}; SECURITY_ATTRIBUTES sat; sat.nLength=sizeof(sat); sat.lpSecurityDescriptor=NULL; sat.bInheritHandle=TRUE; STARTUPINFO st; st.cb=sizeof(st); GetStartupInfo(&st); st.dwFlags=STARTF_USESHOWWINDOW; st.wShowWindow=SW_SHOWNORMAL; CreateProcess(NULL,"tcs.exe",&sat,NULL,TRUE,NULL,NULL,NULL,&st,&pinfo); DWORD f=WaitForInputIdle(pinfo.hProcess,10000); if(f==WAIT_TIMEOUT) MessageBox(NULL,"WAIT_TIMEOUT",NULL,MB_OK); else if(f==WAIT_FAILED) { errmsg(); MessageBox(NULL,"WAIT_FAILED",NULL,MB_OK); } else { MessageBox(NULL,"0",NULL,MB_OK); } } tcs.exe :: Код (Text): void main() { int a; cin>>a; }
Даже если это верно, то это ничего не меняет. Можно заменить main на WinMain и результат не меняется(только что проверил).
Что значит ? Не доверяете? Правильно CUI от GUI отличается не названием main'а, а флагом в заголовке экзешника! Линкеру нужно указать /SUBSYSTEM:CONSOLE вместо /SUBSYSTEM:WINDOWS. Короче, чтоб не мучаться с настройками проекта, создайте новый и укажите Win32 Application, а не Win32 Console Application. Это справедливо для VC++ 6. Это раз! У GUI-приложения должна быть очередь сообщений. Не поленитесь создать окно, хоть скрытое. Это два!
"создайте новый и укажите Win32 Application, а не Win32 Console Application" - Я так и сделал, просто неверно выразился. Короче НЕ РАБОТАЕТ в любом случае!
2 Quantum я ожидаю окончания распаковки sfx RAR архива (который консольный) Код (Text): inv_win WaitForSingleObject, [prinfo.hProcess], INFINITE все работает.
yureckor Речь о WaitForInputIdle. Quantum Приложение, которое вызывает WaitForInputIdle, не может быть консольным. Откуда информация?
WaitForInputIdle находится в user32.dll, который связан с gdi32.dll, а тот создает очередь сообщений при своей инициализации, т.ч. работать должно независимо от CUI\GUI
Очередь сообщений по видимому должна быть у приложения tcs.exe, поскольку процессу вызывающему WaitForInputIdle интересно то, когда все потоки запущенного процесс им процесса окажутся с пустыми очередями сообщений. Если потоков с циклами и соответственно очередями сообщений у запущенного процесса нет (например у консольного приложения), функция и возвернет ошибку. Другое дело что использовать эту функцию в консольном приложении можно также как и в GUI-шном.
У меня на w2k очередь быть не обязана, это легко проверяется, вот 2 консольных приложения 1. target.exe кроме Sleep,5000 ничего не делает, очереди у неё нет 2. create.exe запускает target.exe и вызывает WaitForInputIdle (очередь есть) Т.к. консольное окно create.exe висит 5 секунд, я делаю вывод что WaitForInputIdle работает (хотя по отладчику не скажешь, странно...) 331135518__cui.zip
WinXP,SP2. У меня возвращается ошибка, при запуске консольного приложения "C:\Windows\System32\cmd.exe". Таймаут установлен в 1000, но функция не ждет, а возвращает ошибку сразу. Видимо Sleep как-то обманывает эту функцию. Но самое интересное - GetLastError возвращает значение LastError бывшее до вызова WaitForInputIdle, например ноль. Так-что зря советуют использовать GetLastError в MSDN. Код (Text): SetLastError (0); DWORD res = WaitForInputIdle (hProcess, 1000); if ((DWORD)-1 == res) { int err = GetLastError (); printf ("Error calling WFI, %d ", err); }
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".
q_q точно, согласен, это меня ввело в заблуждение то, что консольное окно target.exe имело имя родительского процесса create.exe
q_q просмотрел Fess exe я делал так (мне необходимо получить данные со скрытой консоли cmd.exe, запущенной на чужом окне) Код (Text): otprav_ret proc lp_komu:DWORD Local m1:strukt_memory Local so:OVERLAPPED Local l1_lc:DWORD, l2_lc:DWORD, l3_lc:DWORD pushad invoke psh_sel_akt invoke fill_memory, ADDR m1, SIZEOF strukt_memory, 0 invoke create_memory, ADDR m1, 32000 invoke fill_memory, ADDR so, SIZEOF OVERLAPPED, 0 mv [so.loffset], 0 invoke sleep, 100 mov ecx, 20 @@1: dec ecx jz @@2 invoke sleep, 200 inva_win PeekNamedPipe, [hReadPipe2], [m1.mem], [m1.len], ADDR l1_lc, ADDR l2_lc, ADDR l3_lc CP eax, 0, Z, @@1 mov eax, [l1_lc] CP eax, 0, Z, @@1 CP eax, [l2_lc], C, @@1 inv_win ReadFile, [hReadPipe2], [m1.mem], [m1.len], ADDR l1_lc, ADDR so @@2: invoke vipolni_far_kom, [m1.mem], [lp_komu], tx("command_ret") invoke close_memory, ADDR m1 invoke po_sel_akt popad ret otprav_ret endp когда создавал cmd.exe, то его ввод/вывод перенаправил на потоки (pipe). Но это все равно не лучший выход, т.к. например запуск на удаленной машине команды dir может привести к тому, что проверка сработает когда выведено только часть информации.
yureckor Если я правильно понял(а возможно и нет, ибо не совсем ясно что есть hReadPipe2, и др. т.е. хотелось бы видеть описание всех функций и переменных, иначе не понятно что для чего), то с помощью PeekNamedPipe узнаётся, есть ли чего-нибудь в потоке вывода программы и если там пусто, то считается, что программа ждёт ввода. Тут есть ещё одна проблема. Программа может чего-нибудь вывести, а потом задуматься надолго, а пока она будет думать, родительский прецесс считает из пайпа и сможет пытаться посылать данные на ввод дочернему, тогда как тот в то же время может выйти из задумчивости. Предполагается, что тот, кто пишет процесс-родитель, не знает ничего о процессе-наследнике.
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? Уточните.
Quantum cmd.exe ничего не знает о том процессе, который запускает, но корректно пишет и читает из его потоков ввода и вывода и не ошибается из-за "задумчивости"(см. мой пост чуть выше) программ.
Fess exe Это не CMD пишет/читает, а сам процесс. Просто он наследует консоль. Я не понял суть проблемы с "задумчивостью". Пайп имеет буффер, в который один процесс помещает данные (в любом количестве) и они там будут храниться пока второй процесс их не прочитает или пока пайп кто-то не разрушит.
Quantum "Это не CMD пишет/читает, а сам процесс. Просто он наследует консоль" - поясните, если можно. Проблема с "задумчивостью" в том, что родительский процесс может считать, что дочерний просит ввода сразу после того, как отправил некоторое количество байтов на вывод. Если же дочерний вывел только часть данных, а потом выполняет какую-то длительную опрерацию, то родительский будет не прав.