Имя пользователя:
Пароль:  
Помощь | Регистрация | Забыли пароль?  | Правила  

Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » AutoIt » [решено] Обмен данными с консольным приложением

Ответить
Настройки темы
[решено] Обмен данными с консольным приложением

Аватара для Coutty

Кот Ти


Сообщения: 7318
Благодарности: 1204


Конфигурация

Профиль | Отправить PM | Цитировать


Вложения
Тип файла: zip gnugo.zip
(608.8 Kb, 6 просмотров)
Хочу написать свой GUI к консольному приложению, однако организовать обмен данными не получается.
Код: Выделить весь код
#include <Constants.au3>

AutoItSetOption("ProvideRunStdout", 1)
AutoItSetOption("ProvideRunStdin", 1)

$PID = Run("gnugo.exe --mode gtp", '', @SW_HIDE, $STDOUT_CHILD + $STDIN_CHILD)
StdinWrite($PID, "version")  ; запрашиваем версию программы
MsgBox(0,0, StdoutRead($PID))   ; и выводим его в окне сообщения
Если запускать программу из консоли с данными параметрами, то там будет пустая строка, ожидающая ввода команд. Например, на запрос version она выдаёт = 3.6. На одни запросы ответ мгновенный, на другие - "после раздумий". Но даже с простым запросом версии ничего не получается. Скрипт просто не передаёт данные программе.

Нашёл на форуме другой вариант:
Код: Выделить весь код
#include <Constants.au3>
#include <Encoding.au3>

AutoItSetOption("ProvideRunStdout", 1)
AutoItSetOption("ProvideRunStdin", 1)

Local $PID = Run(@ComSpec & " /C gnugo.exe --mode gtp", '', @SW_HIDE, $STDOUT_CHILD + $STDIN_CHILD + $STDERR_CHILD)
Local $line

StdinWrite($PID, "version")  ; запрашиваем версию программы
While 1
    $line = StdoutRead($PID) ; и ждём ответа
    If @error Then ExitLoop
WEnd

While 1
    $line = StderrRead($PID)
    If @error Then ExitLoop
    MsgBox(0, "STDERR read:", $line)
WEnd

MsgBox(0,0, _Encoding_866To1251($line))
Здесь вообще никакой реакции - скрипт повисает в памяти вместе с программой.

Подскажите, пожалуйста, что делать) Скрипты и программа прилагаются.

Как разукрашивать скрипты для форума - не знаю, поэтому использую тэг code.

Отправлено: 20:14, 17-04-2011

 

Аватара для kaster

Старожил


Сообщения: 367
Благодарности: 91

Профиль | Отправить PM | Цитировать


Вот небольшой пример, попробуй вставить свою программу и посмотреть
Код: Выделить весь код
; Demonstrates StdoutRead()
#include <Constants.au3>
#include <Encoding.au3>
#include <GUIConstantsEx.au3>
$myapp = 'ping ya.ru'
$hGUI = GUICreate('My Apps output stream', 500, 200)
$hEdit = GUICtrlCreateEdit('', 10, 10, 480, 150)
$hButtonStart = GUICtrlCreateButton('Start', 10, 170, 235, 20)
$hButtonStop = GUICtrlCreateButton('Stop', 255, 170, 235, 20)
;$hButtonEnd =
GUISetState()

Do
	$msg = GUIGetMsg()
	Switch $msg
		 Case $hButtonStart
			Local $pid = Run($myapp, '', @SW_HIDE, $STDERR_CHILD + $STDOUT_CHILD)
			GUICtrlSetData($hEdit, '')
			While 1
				$msg = GUIGetMsg()
				$line = StdoutRead($pid)
				If @error OR $msg = $hButtonStop Then
					ProcessClose($pid)
					GUICtrlSetData($hEdit, GUICtrlRead($hEdit) & '-------------- Stopped -----------------')
					ExitLoop
				EndIf
				If $line Then GUICtrlSetData($hEdit, GUICtrlRead($hEdit) & _Encoding_OEM2ANSI($line))
			Wend
	EndSwitch
Until $msg = $GUI_EVENT_CLOSE

-------
Русское сообщество пользователей AutoIt
autoit@conference.jabber.ru - Конференция на jabber.ru


Отправлено: 20:59, 17-04-2011 | #2



Для отключения данного рекламного блока вам необходимо зарегистрироваться или войти с учетной записью социальной сети.

Если же вы забыли свой пароль на форуме, то воспользуйтесь данной ссылкой для восстановления пароля.


Аватара для kaster

Старожил


Сообщения: 367
Благодарности: 91

Профиль | Отправить PM | Цитировать


что-то не сразу сообразил, что программа требует интеракцию с пользователем. посмотрю, что можно сделать

-------
Русское сообщество пользователей AutoIt
autoit@conference.jabber.ru - Конференция на jabber.ru


Отправлено: 21:22, 17-04-2011 | #3


Аватара для kaster

Старожил


Сообщения: 367
Благодарности: 91

Профиль | Отправить PM | Цитировать


видно, это особенности приложения, но оно не дает взаимодействовать с собой при вызове из скрипта перенаправленными потоками, при первом же приглашении на ввод данных закрывается. вот макет gui, может кто сможет разобраться, так хотя бы GUI не надо будет делать
Код: Выделить весь код
; Demonstrates StdoutRead()
#include <Constants.au3>
#include <Encoding.au3>
#include <GUIConstantsEx.au3>
$myapp = 'gnugo'
$hGUI = GUICreate('My Apps output stream', 500, 200)
$hEditOut = GUICtrlCreateEdit('', 10, 10, 235, 150)
$hEditIn = GUICtrlCreateEdit('', 255, 10, 235, 150)
$hButtonStart = GUICtrlCreateButton('Start', 10, 170, 150, 20)
$hButtonSend = GUICtrlCreateButton('Send comm', 175, 170, 150, 20)
$hButtonStop = GUICtrlCreateButton('Stop', 340, 170, 150, 20)
GUISetState()

Do
	$msg = GUIGetMsg()
	Switch $msg
		 Case $hButtonStart
			Local $pid = Run($myapp, @ScriptDir, @SW_HIDE, $STDOUT_CHILD)
			GUICtrlSetData($hEditOut, '')
			GUICtrlSetState($hButtonStart, $GUI_DISABLE)
			_OutWait()
		Case $hButtonSend
			StdInWrite($pid, GUICtrlRead($hEditIn) & @CRLF)
			GUICtrlSetData($hEditIn, '')
			_OutWait()
	EndSwitch
Until $msg = $GUI_EVENT_CLOSE

Func _OutWait()
	While ProcessExists($pid)
		$msg = GUIGetMsg()
		$line = StdoutRead($pid)
		If $msg = $hButtonStop Then
			ProcessClose($pid)
			GUICtrlSetData($hEditOut, GUICtrlRead($hEditOut) & '-------------- Stopped -----------------')
			GUICtrlSetState($hButtonStart, $GUI_ENABLE)
			ExitLoop
		EndIf
		If $line Then GUICtrlSetData($hEditOut, GUICtrlRead($hEditOut) & _Encoding_OEM2ANSI($line))
		If StringRegExp($line, '\(\d\):') Then ExitLoop
	Wend
EndFunc

-------
Русское сообщество пользователей AutoIt
autoit@conference.jabber.ru - Конференция на jabber.ru


Последний раз редактировалось kaster, 17-04-2011 в 22:31.


Отправлено: 22:25, 17-04-2011 | #4


Аватара для Coutty

Кот Ти


Сообщения: 7318
Благодарности: 1204

Профиль | Отправить PM | Цитировать


Да, прочитать первичные данные мне удавалось (если вызывать gnugo без параметров), но вот передать что-то... В --mode gtp вообще ничего не выходит (ну здесь-то просто не выдаёт окно приветствия).
Цитата kaster:
что-то не сразу сообразил, что программа требует интеракцию с пользователем »
Да. Надо:
1. Запустить
2. Передать команду (version или, например, d4, если без параметров запускать)
3. Прочитать ответ
4. Ожидать следующей команды
Дальше, надеюсь, разберусь.
Цитата kaster:
видно, это особенности приложения, но оно не дает взаимодействовать с собой при вызове из скрипта перенаправленными потоками »
Существует уже куча GUI различной сложности на разных языках (по крайней мере на Java и C++) и даже есть возможность подключения по технологии клиент-сервер, значит как-то всё должно работать. Но нет той оболочки, которая нужна мне.

Последний раз редактировалось Coutty, 18-04-2011 в 04:08.


Отправлено: 03:59, 18-04-2011 | #5


Аватара для kaster

Старожил


Сообщения: 367
Благодарности: 91

Профиль | Отправить PM | Цитировать


Цитата Coutty:
Существует уже куча GUI различной сложности на разных языках »
я имел в виду особенность именно в AutoIt, т.к. после перехвата потока программа сразу завершается

-------
Русское сообщество пользователей AutoIt
autoit@conference.jabber.ru - Конференция на jabber.ru


Отправлено: 05:43, 18-04-2011 | #6


Аватара для Coutty

Кот Ти


Сообщения: 7318
Благодарности: 1204

Профиль | Отправить PM | Цитировать


О! Добился прогресса. Удалось получить ответ от программы.
Код: Выделить весь код
#include <Constants.au3>

AutoItSetOption("ProvideRunStdout", 1)
AutoItSetOption("ProvideRunStdin", 1)

$PID = Run("gnugo.exe --mode gtp", '', @SW_HIDE, $STDIN_CHILD + $STDOUT_CHILD)
Sleep(1000)                            ; даём время gnugo для запуска
StdinWrite($PID, "version" & @CRLF)    ; запрашиваем номер версии

$line = StdoutRead($PID, 1)            ; читаем поток
MsgBox(0,0, $line)
Основные изменения:
1. Даю время на запуск программы. Можно и увеличить на несколько секунд, ничего страшного.
2. При передаче команды добавляем <Enter> (@CRLF)
3. При чтении ответа указываем второй параметр. В справке написано, что это означает максимальное количество прочитываемых символов, но почему-то и 1, и 100 дают одинаковый результат - читается всё.

Итак, ответ получен. Но возникла сложность на следующем этапе - если теперь передать вторую команду
Код: Выделить весь код
StdinWrite($PID, "showboard" & @CRLF)
$line = StdoutRead($PID, 1)
MsgBox(0,0, $line)
то ответ получаем тот же, что и на первую. Даже если поставить секундный интервал ожидания между ними.
Если же вставить "заглушку" StdinWrite($PID), то скрипт завершается на этой инструкции.

Если передавать сразу две команды:
Код: Выделить весь код
StdinWrite($PID, "version" & @CRLF & "showboard" & @CRLF)
то получаем ответ на обе, но следующий отдельный запрос выдаёт повтор.

Отправлено: 18:26, 18-04-2011 | #7


Аватара для kaster

Старожил


Сообщения: 367
Благодарности: 91

Профиль | Отправить PM | Цитировать


Coutty, у меня твой код ничего не показывает. пустой msgbox

-------
Русское сообщество пользователей AutoIt
autoit@conference.jabber.ru - Конференция на jabber.ru


Отправлено: 21:35, 18-04-2011 | #8


Аватара для Coutty

Кот Ти


Сообщения: 7318
Благодарности: 1204

Профиль | Отправить PM | Цитировать


Весьма странно, у меня и сегодня работает...
Но, наверное, не стоило начинать это на AutoIt. Вот только с C# я тем более не разобрался >_<

Отправлено: 03:51, 19-04-2011 | #9


Аватара для Coutty

Кот Ти


Сообщения: 7318
Благодарности: 1204

Профиль | Отправить PM | Цитировать


Мммм... можно сказать, что решилось.
1. Отсылаю команду №1
2. Читаю ответ
3. Отсылаю команду №2
4. Жду 0,5 сек.
5. Читаю ответ

Так ответы получаются разные. Но тоже не совсем гладко. Второй ответ включает в себя и первый тоже. Таким образом, возникает проблема разбора. Вот если бы предыдущий ответ удалялся...
К счастью, протокол GTP предусматривает нумерацию запросов и ответов, т.ч. здесь всё-таки можно что-то придумать.

"Окончательный" код

Код: Выделить весь код
#include <Constants.au3>

AutoItSetOption("ProvideRunStdout", 1)
AutoItSetOption("ProvideRunStdin", 1)

$PID = Run("gnugo.exe --mode gtp", '', @SW_HIDE, $STDIN_CHILD + $STDOUT_CHILD)
Sleep(1000)  ; даём время на запуск
StdinWrite($PID, "1 version" & @CRLF)  ; передаём первую команду

$line = StdoutRead($PID, 1) ; читаем ответ
MsgBox(0,0, $line)


StdinWrite($PID, "2 showboard" & @CRLF) ; передаём вторую команду
Sleep(500) ; выжидаем

$line = StdoutRead($PID, 1) ; читаем ответ
MsgBox(0,0, $line)

Отправлено: 19:40, 19-04-2011 | #10



Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » AutoIt » [решено] Обмен данными с консольным приложением

Участник сейчас на форуме Участник сейчас на форуме Участник вне форума Участник вне форума Автор темы Автор темы Шапка темы Сообщение прикреплено

Похожие темы
Название темы Автор Информация о форуме Ответов Последнее сообщение
[решено] Управление консольным... скрипт-приложением semiono AutoIt 1 07-04-2009 09:27
Прочее - Как организовать обмен данными об ip ? mitiya Сетевые технологии 10 27-02-2009 11:28
Обмен данными между программами Ventil Программирование и базы данных 4 02-11-2004 15:31
Обмен данными между окнами pauluss Вебмастеру 1 25-02-2004 13:58
Обмен данными по инету(sharing) Guest Хочу все знать 1 23-01-2004 18:56




 
Переход