Показать полную графическую версию : [решено] Обмен данными с консольным приложением
Хочу написать свой 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. На одни запросы ответ мгновенный, на другие - "после раздумий". Но даже с простым запросом версии ничего не получается. Скрипт просто не передаёт данные программе.
Нашёл на форуме другой вариант (http://forum.oszone.net/thread-179405.html):
#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.
Вот небольшой пример, попробуй вставить свою программу и посмотреть
; 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
что-то не сразу сообразил, что программа требует интеракцию с пользователем. посмотрю, что можно сделать
видно, это особенности приложения, но оно не дает взаимодействовать с собой при вызове из скрипта перенаправленными потоками, при первом же приглашении на ввод данных закрывается. вот макет 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
Да, прочитать первичные данные мне удавалось (если вызывать gnugo без параметров), но вот передать что-то... В --mode gtp вообще ничего не выходит (ну здесь-то просто не выдаёт окно приветствия).
что-то не сразу сообразил, что программа требует интеракцию с пользователем »
Да. Надо:
1. Запустить
2. Передать команду (version или, например, d4, если без параметров запускать)
3. Прочитать ответ
4. Ожидать следующей команды
Дальше, надеюсь, разберусь.
видно, это особенности приложения, но оно не дает взаимодействовать с собой при вызове из скрипта перенаправленными потоками »
Существует уже куча GUI различной сложности на разных языках (по крайней мере на Java и C++) и даже есть возможность подключения по технологии клиент-сервер, значит как-то всё должно работать. Но нет той оболочки, которая нужна мне.
Существует уже куча GUI различной сложности на разных языках »
я имел в виду особенность именно в AutoIt, т.к. после перехвата потока программа сразу завершается
О! Добился прогресса. Удалось получить ответ от программы.
#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)
то получаем ответ на обе, но следующий отдельный запрос выдаёт повтор.
Coutty, у меня твой код ничего не показывает. пустой msgbox
Весьма странно, у меня и сегодня работает...
Но, наверное, не стоило начинать это на AutoIt. Вот только с C# я тем более не разобрался >_<
Мммм... можно сказать, что решилось.
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)
© OSzone.net 2001-2012
vBulletin v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.