![]() |
Модераторы: feodorv, GremlinProg, xvr, Fixin |
![]() ![]() ![]() |
|
TheDestroyer |
|
||||||
Шустрый ![]() Профиль Группа: Участник Сообщений: 112 Регистрация: 5.11.2007 Репутация: нет Всего: нет |
В интернете повсюду разбросан пример работы с консольными приложениями: http://www.codenet.ru/progr/bcb/pipes.php
После прочтения справки возник следующий вопрос: обязательно ли использовать ReadFile вместе с PeekNamedPipe? Ведь в msdn написано:
Одним из отличий этих функций является то, что ReadFile будет ждать пока не прочитает заданное число байт, а PeekNamedPipe вернет значение в любом случае и программа продолжит выполняться. Соответственно будет ли корректным такое чтение из пайпа: Создание пайпа:
Чтение:
|
||||||
|
|||||||
andrew_121 |
|
|||
![]() Кодофей ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3448 Регистрация: 3.1.2008 Репутация: 2 Всего: 33 |
Все уже написано!
-------------------- Удалил аккаунт. Прощайте! |
|||
|
||||
TheDestroyer |
|
|||
Шустрый ![]() Профиль Группа: Участник Сообщений: 112 Регистрация: 5.11.2007 Репутация: нет Всего: нет |
Спасибо, почти то что надо
![]() Остается следующий вопрос: если использовать данный класс для чтения вывода консольной программы которая может работать достаточно долго, то как понять, что она отработала и закрылась? Необходимо читать вывод в цикле вне класса TChildProc. Т.е.
Но, видимо, использовать eof неправильно. Вставлять обработку прочитанного в сам класс не выход. Как правильно обеспечить такую структуру чтения вывода консольной программы? Это сообщение отредактировал(а) TheDestroyer - 31.5.2009, 18:16 |
|||
|
||||
andrew_121 |
|
|||
![]() Кодофей ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3448 Регистрация: 3.1.2008 Репутация: 2 Всего: 33 |
TheDestroyer, Попробуйте проверять состояние stdin, stdout
Добавлено через 13 минут и 22 секунды вот: http://forum.vingrad.ru/forum/topic-261375...1/view-all.html -------------------- Удалил аккаунт. Прощайте! |
|||
|
||||
TheDestroyer |
|
|||
Шустрый ![]() Профиль Группа: Участник Сообщений: 112 Регистрация: 5.11.2007 Репутация: нет Всего: нет |
Вроде как я это и проверяю в коде предыдущего поста. В приведенной теме поблема немного другая. Вроде получилось сделать так: Объявить хэндл запускаемого процесса PROCESS_INFORMATION piProcInfo глобальным по классу и сделать его public. Цикл чтения получился такой:
|
|||
|
||||
TheDestroyer |
|
||||
Шустрый ![]() Профиль Группа: Участник Сообщений: 112 Регистрация: 5.11.2007 Репутация: нет Всего: нет |
Обнаружилась проблема: если консольное приложение выдает информацию непрерывно, то все читается нормально, а если оно в течение минуты, например, ничего не выдает (просто работает без вывода, потом продолжает выдавать) то функция PeekNamedPipe(FChildStdoutRd, NULL, 0, NULL, &DataSize, NULL); после этой паузы всегда возвращает false и &DataSize = 0, хотя видно, что консольное приложение работает и должно выводить результат. Вот код чтения из пайпа:
Вот цикл чтения:
|
||||
|
|||||
GremlinProg |
|
|||
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2706 Регистрация: 9.8.2005 Где: Тюмень Репутация: 99 Всего: 106 |
TheDestroyer, а не пробовал вместо PeekNamedPipe использовать WaitNamedPipe, она же более логична: подождать, пока не истечет период времени, либо пайп не активирует связь
пример: http://msdn.microsoft.com/en-us/library/aa365592(VS.85).aspx Добавлено через 4 минуты и 19 секунд да, там кстати, заодно и причина твоего выхода из цикла, смотри в самом низу, по ссылке:
-------------------- "Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины." |
|||
|
||||
TheDestroyer |
|
|||
Шустрый ![]() Профиль Группа: Участник Сообщений: 112 Регистрация: 5.11.2007 Репутация: нет Всего: нет |
Да, хорошо бы, но это функция только для именованных пайпов, соответственно не подходит для использования в этом примере.
Нашел в msdn пост по аналогичной проблеме: http://social.msdn.microsoft.com/Forums/en...9-c61c7d8c9f8f/ Видимо, надо использовать именнованные пайпы, как в примере http://msdn.microsoft.com/en-us/library/aa365592(VS.85).aspx Но я никак не пойму как в этом примере указать, что читать надо из конкретного консольного приложения.
К сожалению это не то, т.к. мне надо выводить результат не в цикле чтения из пайпа, а в другом, как показано в моем предыдущем посте. Все еще ищу рабочий пример (а лучше класс) перенаправления вывода консольной программы в свою с помощью пайпов. |
|||
|
||||
TheDestroyer |
|
|||
Шустрый ![]() Профиль Группа: Участник Сообщений: 112 Регистрация: 5.11.2007 Репутация: нет Всего: нет |
Написал тестовую консольную программку:
Проверяю как происходит захват ее вывода. Результат: в самом начале пусто, т.е. PeekNamedPipe возвращает DataSize=0, но как только тестовая программка отработает или может раньше, выплевывает сразу все захваченное из нее. Похоже на буферизацию. Нашел похожую проблему: http://programmersforum.ru/showthread.php?t=20526 там советуют вообще не использовать PeekNamedPipe. Но тут, похоже, надо делать flush или что-то типа него. Подскажите, что можно сделать для опустошения буфера в каждом цикле. чтобы PeekNamedPipe возвращала DataSize!=0 ? |
|||
|
||||
GremlinProg |
|
|||
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2706 Регистрация: 9.8.2005 Где: Тюмень Репутация: 99 Всего: 106 |
ради эксперимента, попробуй в цикле вызывать:
на каждую итерацию, а PeekNamedPipe тут и не нужен, если постоянно (до обрыва) крутить ReadFile, эффект будет такой же (смотри пример, там же все описано) даже если ReadFile вернется с ошибкой ERROR_MORE_DATA в GetLastError, это как раз и будет означать, что буфер на данный момент пустой, но труба еще не закрыта, т.е. можно дальше работать -------------------- "Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины." |
|||
|
||||
TheDestroyer |
|
|||
Шустрый ![]() Профиль Группа: Участник Сообщений: 112 Регистрация: 5.11.2007 Репутация: нет Всего: нет |
Так, вообще ReadFile просто висит если задать большой буфер, эта функция не вернется пока не прочитает столько байт, сколько указано.
Вот пример без PeekNamedPipe http://forum.ixbt.com/topic.cgi?id=40:1426:9#9 В первый момент вывода нет, ReadFile стоит (буфер чтения пробовал 10 байт и 255 байт - всеравно). Стоит некоторое время и потом начинается вывод, т.е. буферизация работает.
не помогают :( Явно работает буферизация, только вот нигде не могу найти как ей можно управлять. Аналогичная проблема встречается у людей в инете, но решения так и не нашел. Приветствуются любые предложения по теме. Это сообщение отредактировал(а) TheDestroyer - 3.6.2009, 18:18 |
|||
|
||||
TheDestroyer |
|
|||
Шустрый ![]() Профиль Группа: Участник Сообщений: 112 Регистрация: 5.11.2007 Репутация: нет Всего: нет |
Помимо вопроса с буфером появились еще:
1. Возможно ли получать вывод консольной программы в свою программу и при этом оставить вывод этой консольной программы таким какой он без перенаправления вывода в мою программу? Т.к. некоторые консольные программы при перенаправлении вывода в мою программу работают некорректно. 2. Возможно ли подсоединиться к уже запущенной консольной программе и получать ее вывод в свою программу? |
|||
|
||||
xvr |
|
||||
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 7046 Регистрация: 28.8.2007 Где: Дублин, Ирландия Репутация: 40 Всего: 223 |
Нет (почти нет). Можно перенаправить вывод консольной программы к себе в пайп, а затем при чтении пайпа дублировать то, что прочлось в первоначальный консольный поток (см. утилиту tee в Linux)
Уточнение - и п1 и п2 можно сделать внедрившись в консольную программу и перехватив API функции вывода, но это ОЧЕНЬ геморойно ![]() |
||||
|
|||||
GremlinProg |
|
|||
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2706 Регистрация: 9.8.2005 Где: Тюмень Репутация: 99 Всего: 106 |
а в windows - это конвеерная обработка "|": http://www.citforum.ru/operating_systems/ois/c050.shtml -------------------- "Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины." |
|||
|
||||
GremlinProg |
|
|||
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2706 Регистрация: 9.8.2005 Где: Тюмень Репутация: 99 Всего: 106 |
пример: type a.txt > b.txt | type b.txt
можно, конечно и PeekNamedPipe использовать, но тут надо иметь хотя бы самый примитивный протокол обмена информацией, по крайней мере, команды: "начало передачи" и "конец передачи" тогда и проблем потери дпанных не будет, независимо от того, какой способ перенаправления используется "снаружи" -------------------- "Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины." |
|||
|
||||
![]() ![]() ![]() |
Правила форума "C/C++: Системное программирование и WinAPI" | |
|
На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы . Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv. |
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | C/C++: Системное программирование и WinAPI | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |