StdIn, StdOut и StdErr. Перенаправление, чтение и записьDelphi , ОС и Железо , DOS и КонсольStdIn, StdOut и StdErr. Перенаправление, чтение и записьАвтор: Горбань С.В. Вообще - я программист молодой, стаж - всего 2 года. И я никак не ожидал, что в век GDI мне придется возится с консолью... Ан нет, пришлось. Начал писать "движок" для собственного сайта. А именно - "Apache 1.x shared module" (dll - линкуется к Апачу и обрабатывает определенные адреса). Написал. Всего три сотни строк. НО умеет кучу всяких полезностей, типа вставлять на страницы данные из файлов (файл в файл), строки и, главное, данные из БД. Все это прекрасно. НО не умеет вставлять результаты работы других файлов (типа как CGI). Ну, думаю, надо сделать. Ага, а как? Вот тут то все и началось... Итак, ЗАДАЧА: запустить процесс (некий файл), передать ему команды и получить от него результаты работы. Вставить полученные результаты на страницу сайта. Причем в целях совместимости механизмы передачи данных ДОЛЖНЫ быть стандартными - StdIn, StdOut, StdErr. Поискал на КД. Нашел вот такую штуку: Как переназначить StdOut в файл для консольной программы запускаемой по CreateProcess Хорошая статья, но мне-то НЕ в ФАЙЛ, а в ПРОГРАММУ надо! Автор (Спасибо ему!!!) предусмотрительно указал ссылки на полезные раздел справки - "Creating a Child Process with Redirected Input and Output". Лезем туда. Ууууух... Круто. В общем, каких-то два дня ковыряния и вуаля! Работает! Получился небольшой такой класс... За кривизну некоторых мест, типа отсутствия проверок - НЕ бить! (по крайней мере ногами :-)). Кому надо - тот сам вставит. (Вот так и рождается "кривой" код. Типа сейчас лень, потом добавлю... Ага... Через час уже забудешь!!!) В общем - перехожу таки к технике дела. Для передачи данных используются "безымянные" (Anonymus) "каналы" (Pipes). Чтобы заставить программу писать в (читать из) канал (а) - просто подменяем соответствующие Std(In, Out, Err). Программа и знать не будет, что ее данные уходят в "трубу" а не на реальную консоль. При создании каналов есть одна ВАЖНАЯ особенность. Создаем-то мы их в своем процессе (Parent) а использовать будем и в дочернем. (Учтите! дочерний процесс НЕ будет знать, что использует КАНАЛ! НО будет его использовать...). Так, вот, чтобы дочерний процесс мог нормально работать - хэндлы канала должны быть НАСЛЕДУЕМЫМИ. Чтобы это обеспечить - надо правильно заполнить структуру SECURITY_ATTRIBUTES используемую при вызове CreatePipe:
Заполнили? Молодцы! Теперь создаем каналы (я делаю только два, StdErr мне не нужен):
Создали? Если нет - то дальше ловить нечего, поэтому генерим Exception'ы... Есть еще одна тонкость. У нас Все созданные хэндлы наследуемые! А дочернему процессу понадобятся только два... Поэтому:
Дубликаты у нас в Tmp1 и Tmp2, теперь:
Ура! Теперь можем создавать дочерний процесс!
Причем CreateChildProcess - это не API - это моя функция! Вот она:
Здесь важное значение имеют вот эти строчки:
Первые две - понятно. А третья - читайте Хелп! Там все написано...
Самые умные (то есть те, кто ухитрился дочитать до этого места :-))) спросят: А дальше - мы можем с ентим процессом общаться! Например вот так:
Это мы посылаем данные на StdIn процесса. Читать - несколько сложнее. Нам же не надо вешать всю нашу программу только потому, что процесс не желает нам ничего сообщать??? А ReadFile - функция синхронная и висит - пока не прочитает! Если заранее известно, чего и сколько ДОЛЖЕН выдать процесс, то еще ничего... А если нет? А если нет - делаем хитрый финт ушами :-) Есть у Мелко-Мягких такая ф-ия PeekNamedPipe. Не покупайтесь, на то, что она "Named" - фигня! Она прекрасно работает а анонимными пайпами! (кто не верит - можете почитать хелп) Поэтому делаем так:
Ну, вот, как я и говорил - работает. Даже слишком хорошо. Как я и говорил - эта вся бодяга для Web сервера. Ну, беру я в качестве файла - format.exe.... Ндаааа.... Если честно - с format'ом я не прверял - а вот help c парметрами и "net use" прошли на ура! Так что пришлось резко думать, как ограничить список разрешенных для запуска программ.... В общем, кому лень разбираться - вот вам исходники модуля с готовым классом. А вот пример его использования:
Не правда ли просто? Скачать:
Статья рассказывает о перенаправлении стандартных потоков ввода/вывода в консольной программе, созданной с помощью API Windows для запуска файлов из веб-сайта. Автор описывает класс, который позволяет запускать процесс, передавать команды и получать резул Комментарии и вопросыПолучайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта. :: Главная :: DOS и Консоль ::
|
||||||||||||||
©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007 |