Что нового

AppInteract - Интеракция между скриптами

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 472
Репутация
2 402
Версия AutoIt
3.3.14.5
Версия
0.5
Подобных примеров и библиотек уже множество (включая и мою же Container), вот отличия у этого варианта:
  • Стабильность
  • Возможность передавать массивы (пока только 2D)
  • Возможность возврата от процесса с котором вошли в интеракцию (пока только текст до 1024 байт)
  • Возможность двусторонней интеракции

Примечания:
* Эта библиотека регистрирует сообщение WM_COPYDATA, если ваш скрипт или другая библиотека использует это сообщение, необходимо сделать вызов __AppInteract_WM_COPYDATA($hWnd, $iMsg, $wParam, $lParam) из подобной функции скрипта или библиотеки.
* Не используйте задержку в функции принимающей сообщения, возврат должен быть как можно раньше.
Script1.au3:
Код:
#include <GUIConstantsEx.au3>
#include <ListViewConstants.au3>
#include <Array.au3>
#include 'AppInteract.au3'

Global $iApp = 1

Global $sApp_Name = 'My App' & $iApp
Global $sSend_App_Name = 'My App' & Mod($iApp, 2) + 1
Global $sSend_Script_Name = 'Script' & Mod($iApp, 2) + 1 & '.' & (@Compiled ? 'exe' : 'au3')

Global $iGUI_Width = 600
Global $iGUI_Left = 100 + ($iGUI_Width * ($iApp - 1)) + (10 * ($iApp - 1))

_AppInteract_SetReceiver($sApp_Name, '_Receiver')

$hGUI = GUICreate(@ScriptName & ' - AppInteract Example', $iGUI_Width, 400, $iGUI_Left, 20)

GUICtrlCreateLabel('Please run ' & $sSend_Script_Name & ' and enter some data to send:', 10, 5, -1, 15)
$iEdit = GUICtrlCreateEdit(StringFormat('Send\r\nThis\r\nData\r\nTo\r\n%s', $sSend_Script_Name), 10, 20, 580, 150)

GUICtrlCreateLabel('Received:', 10, 175, -1, 15)
$iReceiver_LV = GUICtrlCreateListView('Type|Data', 10, 190, 580, 170)
GUICtrlSendMsg($iReceiver_LV, $LVM_SETCOLUMNWIDTH, 0, 285)
GUICtrlSendMsg($iReceiver_LV, $LVM_SETCOLUMNWIDTH, 1, 285)

GUICtrlCreateLabel('Send to ' & $sSend_Script_Name & ' as:', 20, 373)
$iSendStr_Bttn = GUICtrlCreateButton('String', 150, 370, 70, 20)
$iSendArr_Bttn = GUICtrlCreateButton('Array', 230, 370, 70, 20)
$iSendBin_Bttn = GUICtrlCreateButton('Binary', 310, 370, 70, 20)

GUISetState(@SW_SHOW, $hGUI)
WinSetOnTop($hGUI, '', 1)

While 1
    $nMsg = GUIGetMsg()
  
    Switch $nMsg
        Case $GUI_EVENT_CLOSE
            Exit
        Case $iSendStr_Bttn, $iSendArr_Bttn, $iSendBin_Bttn
            $vData = GUICtrlRead($iEdit)
          
            Switch $nMsg
                Case $iSendArr_Bttn
                    $vData = StringSplit(StringStripCR($vData), @LF)
                Case $iSendBin_Bttn
                    $vData = StringToBinary($vData)
            EndSwitch
          
            _AppInteract_Send($sSend_App_Name, $vData, @AutoItExe)
          
            If @error Then
                MsgBox(48, @ScriptName, 'Unable to send, probably ' & $sSend_Script_Name & ' is not executed!', 0, $hGUI)
            EndIf
    EndSwitch
WEnd

Func _Receiver($vData)
    Local $sData = $vData
    Local $sType = VarGetType($vData)
  
    Switch $sType
        Case 'Array'
            $sData = _ArrayToString($vData, '~', -1, -1, Chr(10))
        Case 'Binary'
            $sData = BinaryToString($vData)
    EndSwitch
  
    GUICtrlCreateListViewItem($sType & '|' & $sData, $iReceiver_LV)
EndFunc


Script2.au3:
Код:
#include <GUIConstantsEx.au3>
#include <ListViewConstants.au3>
#include <Array.au3>
#include 'AppInteract.au3'

Global $iApp = 2

Global $sApp_Name = 'My App' & $iApp
Global $sSend_App_Name = 'My App' & Mod($iApp, 2) + 1
Global $sSend_Script_Name = 'Script' & Mod($iApp, 2) + 1 & '.' & (@Compiled ? 'exe' : 'au3')

Global $iGUI_Width = 600
Global $iGUI_Left = 100 + ($iGUI_Width * ($iApp - 1)) + (10 * ($iApp - 1))

_AppInteract_SetReceiver($sApp_Name, '_Receiver')

$hGUI = GUICreate(@ScriptName & ' - AppInteract Example', $iGUI_Width, 400, $iGUI_Left, 20)

GUICtrlCreateLabel('Please run ' & $sSend_Script_Name & ' and enter some data to send:', 10, 5, -1, 15)
$iEdit = GUICtrlCreateEdit(StringFormat('Send\r\nThis\r\nData\r\nTo\r\n%s', $sSend_Script_Name), 10, 20, 580, 150)

GUICtrlCreateLabel('Received:', 10, 175, -1, 15)
$iReceiver_LV = GUICtrlCreateListView('Type|Data', 10, 190, 580, 170)
GUICtrlSendMsg($iReceiver_LV, $LVM_SETCOLUMNWIDTH, 0, 285)
GUICtrlSendMsg($iReceiver_LV, $LVM_SETCOLUMNWIDTH, 1, 285)

GUICtrlCreateLabel('Send to ' & $sSend_Script_Name & ' as:', 20, 373)
$iSendStr_Bttn = GUICtrlCreateButton('String', 150, 370, 70, 20)
$iSendArr_Bttn = GUICtrlCreateButton('Array', 230, 370, 70, 20)
$iSendBin_Bttn = GUICtrlCreateButton('Binary', 310, 370, 70, 20)

GUISetState(@SW_SHOW, $hGUI)
WinSetOnTop($hGUI, '', 1)

While 1
    $nMsg = GUIGetMsg()
  
    Switch $nMsg
        Case $GUI_EVENT_CLOSE
            Exit
        Case $iSendStr_Bttn, $iSendArr_Bttn, $iSendBin_Bttn
            $vData = GUICtrlRead($iEdit)
          
            Switch $nMsg
                Case $iSendArr_Bttn
                    $vData = StringSplit(StringStripCR($vData), @LF)
                Case $iSendBin_Bttn
                    $vData = StringToBinary($vData)
            EndSwitch
          
            _AppInteract_Send($sSend_App_Name, $vData, @AutoItExe)
          
            If @error Then
                MsgBox(48, @ScriptName, 'Unable to send, probably ' & $sSend_Script_Name & ' is not executed!', 0, $hGUI)
            EndIf
    EndSwitch
WEnd

Func _Receiver($vData)
    Local $sData = $vData
    Local $sType = VarGetType($vData)
  
    Switch $sType
        Case 'Array'
            $sData = _ArrayToString($vData, '~', -1, -1, Chr(10))
        Case 'Binary'
            $sData = BinaryToString($vData)
    EndSwitch
  
    GUICtrlCreateListViewItem($sType & '|' & $sData, $iReceiver_LV)
EndFunc
 
Автор
G.Sandler
Источник
Ссылка на источник

Вложения

Последнее редактирование:

Webarion

Знающий
Сообщения
83
Репутация
5
А почему $hWnd = WinGetHandle($sTitle) в _AppInteract_Send закомментировано?
У меня без неё не работает. У меня __AppInteract_ProcGetPath не получает путь, поэтому, только эта строка определяет $hWnd.
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 472
Репутация
2 402
почему $hWnd = WinGetHandle($sTitle) в _AppInteract_Send закомментировано?
У меня получает и без этого. Идея была в том чтобы скрипты не конфликтовали с другими, а также чтобы был обмен...

У меня без неё не работает
Странно. Запускал из под учётной записи администратора?

У меня __AppInteract_ProcGetPath не получает путь
А если заменить на _WinAPI_GetProcessFileName?
 
Последнее редактирование:

Webarion

Знающий
Сообщения
83
Репутация
5
У меня получает и без этого. Идея была в том чтобы скрипты не конфликтовали с другими, а также чтобы был обмен...
Странно. Запускал из под учётной записи администратора?
А если заменить на _WinAPI_GetProcessFileName?
Под админом тоже не работает. _WinAPI_GetProcessFileName работает только в нескомпилированных скриптах.
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 472
Репутация
2 402
Обновление:

v0.2
* Улучшена двусторонняя интеракция.
+ Добавлен необязательный параметр $sCmdLine для проверки ком. строки исполняемого файла.
* Изменены примеры.
 

Webarion

Знающий
Сообщения
83
Репутация
5
Не работает в том примере что я выложил? скрипты скомпилированы?
Версия 0.2 работает отлично. И под админом и без него. Скомпилированные скрипты тоже работают. Здорово!
Сообщение автоматически объединено:

Ещё было бы здорово, если бы был такой функционал: отправил данные получателю, получатель сделал своё дело и вернул новые данные. Т.е. как-то так:
Код:
$vReturn = _AppInteract_Send(...) ; в $vReturn ответ от получателя
...
Func _Receiver($vData)
    ...
    Return $aArray; Ответ отправителю
EndFunc
 
Последнее редактирование:
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 472
Репутация
2 402
отправил данные получателю, получатель сделал своё дело и вернул новые данные
Ну так в чём проблема?

Запускаем получатель первым:
Код:
#include <GUIConstantsEx.au3>
#include 'AppInteract.au3'

Global $sApp_Name = 'My App2'
Global $sSend_App_Name = 'My App1'

_AppInteract_SetReceiver($sApp_Name, '_Receiver')

While 1
    Sleep(10)
WEnd

Func _Receiver($vData)
    _AppInteract_Send($sSend_App_Name, 'OK')
    Exit
EndFunc


Потом запускаем отправитель:
Код:
#include <GUIConstantsEx.au3>
#include 'AppInteract.au3'

Global $sApp_Name = 'My App1'
Global $sSend_App_Name = 'My App2'

Global $vRet = ''

_AppInteract_SetReceiver($sApp_Name, '_Receiver')
_AppInteract_Send($sSend_App_Name, 'Ok?')
If @error Then Exit

While $vRet = ''
    Sleep(10)
WEnd

ConsoleWrite($vRet & @CRLF)

Func _Receiver($vData)
    $vRet = $vData
EndFunc


Да, было бы удобнее сразу получать результат, но нужно подумать как это реализовать...
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 472
Репутация
2 402
По идее вот так должно было бы сработать:

Код:
Func _AppInteract_Send($sAppName, $vData, $sPath = '', $sCmdLine = '')
    ...
   
    ;Send command to receiver
    $aRet = DllCall('user32.dll', 'ptr', 'SendMessage', 'hwnd', $hWnd, 'uint', $WM_COPYDATA, 'ptr', 0, 'ptr', DllStructGetPtr($stData))
    $iErr = @error
    
    $stData = DllStructCreate('dword iLen;ptr pStr', Ptr($aRet[0]))
    $stStr = DllStructCreate('wchar sStr[' & DllStructGetData($stData, 'iLen') & ']', DllStructGetData($stData, 'pStr'))
    
    Return DllStructGetData($stStr, 'sStr')
   
    ...
EndFunc

Func __AppInteract_WM_COPYDATA($hWnd, $iMsg, $wParam, $lParam)
    ...
   
    $vRet = Call($sAPPINTRCT_RECEIVER, $sStr)
    
    $iLen = (StringLen($vRet) * 2) + 3
    $stData = DllStructCreate('dword iLen;ptr pStr')
    $stStr = DllStructCreate('wchar sStr[' & $iLen & ']')
    
    DllStructSetData($stStr, 'sStr', $vRet)
    DllStructSetData($stData, 'iLen', $iLen)
    DllStructSetData($stData, 'pStr', DllStructGetPtr($stStr))
    
    Return DllStructGetPtr($stData)
EndFunc


Ведь __AppInteract_WM_COPYDATA возвращает указатель на структуру, и уже по нему можно читать данные ($aRet[0] это и есть наш указатель), но видимо что то я не учитываю.
У меня скрипт вываливается с переполнением памяти.
 
Последнее редактирование:
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 472
Репутация
2 402
Обновление:

v0.3
+ Добавлена возможность возвращать значение от процесса с которым была вызвана интеракция.
+ Для возможности возврата, был добавлен необязательный параметр $sRetAppName для функции _AppInteract_Send.
* Небольшие коррекции.
+ Добавлен пример показывающий как _AppInteract_Send может получать обратный возврат данных.
 

Webarion

Знающий
Сообщения
83
Репутация
5
Привет! Хм, интересно и здорово!
Если не против, подкину некоторые идеи, того, как с моей точки зрения, должен работать обмен между процессами, может будет спортивный интерес на счёт этого?
Я делал подобное, но правда не хватило стимула разобраться с структурами DLL, сделал через дополнительный Edit в создаваемой форме. А хотелось бы, чтобы это была грамотная библиотека от грамотного человека. Что скажешь?
Сообщение автоматически объединено:

Для интереса скажу, что, я пробовал все предложенные интеракции на форуме. Даже, к сожалению неизвестно куда девшийся Yashied, не помог мне в этом, в своих проектах. Я уверен, что это возможно, средствами AutiIt, так как, у меня, не такие уж заоблачные запросы. Но, есть идеи! Например, у меня был проект, который соответствовал этим идеям, но не до конца. Мне удалось это реализовать, почти так, как хотел, чтобы работало стабильно. Но скрипт кустарный, делал по своим возможностям.
Но, с моей точки зрения, было бы здорово, видеть подобный алгоритм, от более знающих людей, а тем более реализацию такого принципа, как интеракция.
 
Последнее редактирование:
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 472
Репутация
2 402
Если не против, подкину некоторые идеи, того, как с моей точки зрения, должен работать обмен между процессами
Я всегда открыт для новых идей.
Сейчас пытаюсь реализовать передачу любых типов данных, не только строк и одномерных массивов.
Кстати текущая версия не поддерживает x64, в следующей исправлю (замена 'dword iIsArr;dword iLen;ptr pStr' на 'ulong_ptr iIsArr;dword_ptr iLen;ptr pStr')
 
Последнее редактирование:

Webarion

Знающий
Сообщения
83
Репутация
5
Отлично, я напишу некоторые соображения.

1. Ниже, выкладываю тестовый скрипт. Считаю, для тестирования, скрипты отправителя и получателя должны быть идентичными, за исключением идентификаторов $sApp_Name, $sSend_App_Name. Первый тестовый скрипт постоянно отправляет данные второму, через разные промежутки времени, и должен уметь получить ответ, именно на свой запрос. Второй скрипт, при этом, также отправляет данные первому, поэтому, каждый из них должен не только отправить и получить ответ на свой запрос, но при этом ещё уметь постоянно получать входящие сообщения и отвечать на них.
В текущий момент в версии 0.3, один тестовый скрипт стабильно отправляет и получает ответ, только в том случае, если не запускать отправку второго.

2. Возможность ожидать получателя несколько секунд (или заданный промежуток времени) если его нет в системе.
3. Не должно иметь значения, какой скрипт запускается первым.
4. Возможность жизни отправленного сообщения, в регулируемом диапазоне времени. Если в течении определённого времени, когда, после отправки сообщения, получателя не существовало, но, в этот промежуток времени, он появился, то он сможет прочитать, все последовательно входящие сообщения, которые ещё живы, в заданный промежуток времени (пункт под вопросом, возможно он относится к пунктам 2 и 4, подумаю, хотя реализация здесь другая).
5. Возможность запустить скрипт, либо скомпилированный скрипт, если он не запущен и если указан к нему путь. Если есть указание, что скрипт больше не понадобится, закрыть его.
6. Библиотека имеет способность создать несколько отправителей и получателей в одном скрипте. Такое мне понадобилось, когда загружались модули не только через их внешний запуск, но и через #include, вторые были системными, первые пользовательскими. Это дало одинаковую архитектуру общения для всех модулей. И практически, для библиотеки не имеет значения, инклюдит основной скрипт модуль или запускает его внешне.

7. Конечно же, хочется иметь возможность передавать и получать ответ в виде разных типов данных.

Пока-что всё. Если ещё что-то придумаю, напишу))

Вот тестовый скрипт(для отправителя и получателя скрипты одинаковые, меняются только идентификаторы):
Код:
#include '..\AppInteract.au3'

#include <GuiListView.au3>
#include <ButtonConstants.au3>
#include <GUIConstantsEx.au3>
#include <ListViewConstants.au3>
#include <WindowsConstants.au3>

Global $sApp_Name = 'My App1'
Global $sSend_App_Name = 'My App2'

$aProgman  = WinGetPos( "[CLASS:Progman]")
Local $iLeft = StringRegExp($sApp_Name,'1$',0) ? ($aProgman[2]/2)-620 : ($aProgman[2]/2)+5
Global $iRun = False, $ButtonStart, $ButtonStop

$Form1 = GUICreate("Form " & $sApp_Name, 615, 481, $iLeft, 111)
$GroupOut = GUICtrlCreateGroup("ИСХОДЯЩИЕ", 4, 8, 605, 197)
$ListViewOut = GUICtrlCreateListView("№|Отправляемое сообщение|Ответ на эту отправку", 12, 28, 589, 169)
GUICtrlSendMsg(-1, $LVM_SETCOLUMNWIDTH, 0, 50)
GUICtrlSendMsg(-1, $LVM_SETCOLUMNWIDTH, 1, 255)
GUICtrlSendMsg(-1, $LVM_SETCOLUMNWIDTH, 2, 255)
GUICtrlCreateGroup("", -99, -99, 1, 1)
$GroupIn = GUICtrlCreateGroup("ВХОДЯЩИЕ", 4, 212, 605, 209)
$ListViewIn = GUICtrlCreateListView("Полученные сообщения|Возвращаем ответ", 12, 232, 589, 181)
GUICtrlSendMsg(-1, $LVM_SETCOLUMNWIDTH, 0, 280)
GUICtrlSendMsg(-1, $LVM_SETCOLUMNWIDTH, 1, 280)
GUICtrlCreateGroup("", -99, -99, 1, 1)
$ButtonStart = GUICtrlCreateButton("Старт отправки", 87, 432, 200, 33)
$ButtonStop = GUICtrlCreateButton("Стоп отправки", 324, 432, 200, 33)
GUISetState(@SW_SHOW)

GUIRegisterMsg($WM_COMMAND, "WM_COMMAND")

_AppInteract_SetReceiver($sApp_Name, '_Receiver')

While 1
        $msg = GUIGetMsg()
        Switch $msg
            Case $GUI_EVENT_CLOSE
                Exit
        EndSwitch
    If $iRun=True Then
        Local $iRnd = Random(11111, 99999, 1)
        Local $sSendMessage = 'сообщение №' & $iRnd
        GUICtrlCreateListViewItem($iRnd & '|' & $sSendMessage, $ListViewOut)
        Local $vResponse = _AppInteract_Send($sSend_App_Name, $sSendMessage, '', '', $sApp_Name); ОТПРАВКА ДАННЫХ И ПОЛУЧЕНИЕ ОТВЕТА

        If $vResponse = '0' Then $vResponse = 'Нет ответа'

        Local $aID = StringRegExp($vResponse, '^.*№(\d+).*$', 1)
        If IsArray($aID) And UBound($aID) = 1 Then
            Local $iIndFind = _GUICtrlListView_FindInText($ListViewOut, $aID[0])
        Else
            Local $iIndFind = _GUICtrlListView_FindInText($ListViewOut, $iRnd)
        EndIf
            _GUICtrlListView_SetItem($ListViewOut, $vResponse, $iIndFind, 2)
            _GUICtrlListView_EnsureVisible($ListViewOut, $iIndFind)
        Sleep(Random(10, 1000, 1))
    Else

    EndIf
WEnd

Func _Receiver($vMsg); ПОЛУЧЕНИЕ ДАННЫХ И ОТПРАВКА ОТВЕТА
    Local $sRetTxt = 'Ответ на ' & $vMsg
    Local $aID = StringRegExp($vMsg, '^.*№(\d+).*$', 1)
    If IsArray($aID) And UBound($aID) = 1 Then
        GUICtrlCreateListViewItem($vMsg & '|' & $sRetTxt, $ListViewIn)
        _GUICtrlListView_EnsureVisible($ListViewIn, _GUICtrlListView_GetItemCount($ListViewIn)-1)
    EndIf
    Return $sRetTxt; Возвращаетм ответ отправителю
EndFunc   ;==>_Receiver


Func WM_COMMAND($hWnd, $Msg, $wParam, $lParam)
        Switch BitAND($wParam, 0x0000FFFF)
            Case $ButtonStart
                $iRun=True
            Case $ButtonStop
                $iRun=False
        EndSwitch
EndFunc
 
Последнее редактирование:
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 472
Репутация
2 402
Это всё можно устроить внутри скрипта и не обязательно вешать на библиотеку, т.к её функция отправлять и получать данные, не более.
Тут нужно организовать грамотную очередь и обработку.

Чуть позже выложу экспериментальную версию где поддерживаются многие типы данных (за исключением структур), а также с похожим примером что и выше (уже набросал).
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 472
Репутация
2 402
В общем вот прикрепил, поиграйся :morning: .
 

Вложения

Webarion

Знающий
Сообщения
83
Репутация
5
Тествовый скрипт под новую версию:
Код:
#include '..\AppInteract.au3'

#include <GuiListView.au3>
#include <ButtonConstants.au3>
#include <GUIConstantsEx.au3>
#include <ListViewConstants.au3>
#include <WindowsConstants.au3>

Global $sApp_Name = 'My App1'
Global $sSend_App_Name = 'My App2'
FileChangeDir('..\')

$aProgman = WinGetPos("[CLASS:Progman]")
Local $iLeft = StringRegExp($sApp_Name, '1$', 0) ? ($aProgman[2] / 2) - 620 : ($aProgman[2] / 2) + 5
Global $iRun = False, $ButtonStart, $ButtonStop, $ListViewOut, $ListViewIn

$Form1 = GUICreate("Form " & $sApp_Name, 615, 481, $iLeft, 111)
$GroupOut = GUICtrlCreateGroup("ИСХОДЯЩИЕ", 4, 8, 605, 197)
$ListViewOut = GUICtrlCreateListView("№|Отправляемое сообщение|Ответ на эту отправку", 12, 28, 589, 169)
GUICtrlSendMsg(-1, $LVM_SETCOLUMNWIDTH, 0, 50)
GUICtrlSendMsg(-1, $LVM_SETCOLUMNWIDTH, 1, 255)
GUICtrlSendMsg(-1, $LVM_SETCOLUMNWIDTH, 2, 255)
GUICtrlCreateGroup("", -99, -99, 1, 1)
$GroupIn = GUICtrlCreateGroup("ВХОДЯЩИЕ", 4, 212, 605, 209)
$ListViewIn = GUICtrlCreateListView("Полученные сообщения|Возвращаем ответ", 12, 232, 589, 181)
GUICtrlSendMsg(-1, $LVM_SETCOLUMNWIDTH, 0, 280)
GUICtrlSendMsg(-1, $LVM_SETCOLUMNWIDTH, 1, 280)
GUICtrlCreateGroup("", -99, -99, 1, 1)
$ButtonStart = GUICtrlCreateButton("Старт отправки", 87, 432, 200, 33)
$ButtonStop = GUICtrlCreateButton("Стоп отправки", 324, 432, 200, 33)
GUISetState(@SW_SHOW)

GUIRegisterMsg($WM_COMMAND, "WM_COMMAND")

_AppInteract_SetReceiver($sApp_Name, '_Receiver')

While 1
    $Msg = GUIGetMsg()
    Switch $Msg
        Case $GUI_EVENT_CLOSE
            Exit
    EndSwitch
    If $iRun = True Then
        Local $iRnd = Random(11111, 99999, 1)
        Local $sSendMessage = 'сообщение №' & $iRnd
        GUICtrlCreateListViewItem($iRnd & '|' & $sSendMessage, $ListViewOut)
        Local $vResponse = _AppInteract_Send($sSend_App_Name, $sSendMessage, @AutoItExe); ОТПРАВКА ДАННЫХ И ПОЛУЧЕНИЕ ОТВЕТА
        If $vResponse = '0' Then $vResponse = 'Нет ответа'

        Local $aID = StringRegExp($vResponse, '^.*№(\d+).*$', 1)
        If IsArray($aID) And UBound($aID) = 1 Then
            Local $iIndFind = _GUICtrlListView_FindInText($ListViewOut, $aID[0])
        Else
            Local $iIndFind = _GUICtrlListView_FindInText($ListViewOut, $iRnd)
        EndIf
        _GUICtrlListView_SetItem($ListViewOut, $vResponse, $iIndFind, 2)
        _GUICtrlListView_EnsureVisible($ListViewOut, $iIndFind)
    EndIf
    Sleep(Random(10, 1000, 1))
WEnd

Func _Receiver($vMsg); ПОЛУЧЕНИЕ ДАННЫХ И ОТПРАВКА ОТВЕТА
    ConsoleWrite($vMsg & @CRLF)
    Local $sRetTxt = 'Ответ на ' & $vMsg
    Local $aID = StringRegExp($vMsg, '^.*№(\d+).*$', 1)
    If IsArray($aID) And UBound($aID) = 1 Then
        GUICtrlCreateListViewItem($vMsg & '|' & $sRetTxt, $ListViewIn)
        _GUICtrlListView_EnsureVisible($ListViewIn, _GUICtrlListView_GetItemCount($ListViewIn) - 1)
    EndIf
    Return $sRetTxt; Возвращаетм ответ отправителю
EndFunc   ;==>_Receiver

Func WM_COMMAND($hWnd, $Msg, $wParam, $lParam)
    Switch BitAND($wParam, 0x0000FFFF)
        Case $ButtonStart
            $iRun = True
        Case $ButtonStop
            $iRun = False
    EndSwitch
EndFunc   ;==>WM_COMMAND

Уже есть прогресс. Но, всё же как и в предыдущем варианте, стабильность только при запуске первого скрипта. Как только запускаю отправку во втором, появляются глюки, скрипт читает свои же сообщения и накладывает их друг на друга. Скриншот:

SciTE_G9Qig5dJqX.png
 
Последнее редактирование:
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 472
Репутация
2 402
С версией 0.3 данный пример работает хорошо.
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 472
Репутация
2 402
И зачем в примере WM_COMMAND?
Вот мой вариант:

Код:
#include '..\..\AppInteract.au3'

#include <GuiListView.au3>
#include <ButtonConstants.au3>
#include <GUIConstantsEx.au3>
#include <ListViewConstants.au3>
#include <WindowsConstants.au3>

Global $sApp_Name = 'My App1'
Global $sSend_App_Name = 'My App2'

FileChangeDir('..\')

$aProgman = WinGetPos("[CLASS:Progman]")
$iLeft = StringRegExp($sApp_Name, '1$', 0) ?($aProgman[2] / 2) - 620 :($aProgman[2] / 2) + 5

$Form1 = GUICreate("Form " & $sApp_Name, 615, 481, $iLeft, 111)
$GroupOut = GUICtrlCreateGroup("ИСХОДЯЩИЕ", 4, 8, 605, 197)
$ListViewOut = GUICtrlCreateListView("№|Отправляемое сообщение|Ответ на эту отправку", 12, 28, 589, 169)
GUICtrlSendMsg(-1, $LVM_SETCOLUMNWIDTH, 0, 50)
GUICtrlSendMsg(-1, $LVM_SETCOLUMNWIDTH, 1, 255)
GUICtrlSendMsg(-1, $LVM_SETCOLUMNWIDTH, 2, 255)
GUICtrlCreateGroup("", -99, -99, 1, 1)
$GroupIn = GUICtrlCreateGroup("ВХОДЯЩИЕ", 4, 212, 605, 209)
$ListViewIn = GUICtrlCreateListView("Полученные сообщения|Возвращаем ответ", 12, 232, 589, 181)
GUICtrlSendMsg(-1, $LVM_SETCOLUMNWIDTH, 0, 280)
GUICtrlSendMsg(-1, $LVM_SETCOLUMNWIDTH, 1, 280)
GUICtrlCreateGroup("", -99, -99, 1, 1)
$ButtonStart = GUICtrlCreateButton("Старт отправки", 87, 432, 200, 33)
$ButtonStop = GUICtrlCreateButton("Стоп отправки", 324, 432, 200, 33)
GUISetState(@SW_SHOW)

_AppInteract_SetReceiver($sApp_Name, '_Receiver')

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
        Case $ButtonStart
            AdlibRegister('_Send', 10)
        Case $ButtonStop
            AdlibUnRegister('_Send')
    EndSwitch
WEnd

Func _Send()
    
Local Static $iTimer = 0
    Local Static $iRandom = 0
    
    If $iTimer And TimerDiff($iTimer) < $iRandom Then
        Return
    EndIf
    
    $iRandom = Random(10, 1000, 1)
    $iTimer = TimerInit()
   
    Local $iRnd = Random(11111, 99999, 1)
    Local $sSendMessage = 'сообщение №' & $iRnd
    GUICtrlCreateListViewItem($iRnd & '|' & $sSendMessage, $ListViewOut)
   
    Local $vResponse = _AppInteract_Send($sSend_App_Name, $sSendMessage, @AutoItExe) ; ОТПРАВКА ДАННЫХ И ПОЛУЧЕНИЕ ОТВЕТА
    If @error Then $vResponse = 'Нет ответа'
   
    Local $aID = StringRegExp($vResponse, '^.*№(\d+).*$', 1)
   
    If IsArray($aID) And UBound($aID) = 1 Then
        Local $iIndFind = _GUICtrlListView_FindInText($ListViewOut, $aID[0])
    Else
        Local $iIndFind = _GUICtrlListView_FindInText($ListViewOut, $iRnd)
    EndIf
   
    _GUICtrlListView_SetItem($ListViewOut, $vResponse, $iIndFind, 2)
    _GUICtrlListView_EnsureVisible($ListViewOut, $iIndFind)
EndFunc

Func _Receiver($vMsg) ; ПОЛУЧЕНИЕ ДАННЫХ И ОТПРАВКА ОТВЕТА
    ConsoleWrite($vMsg & @CRLF)
   
    Local $sRetTxt = 'Ответ на ' & $vMsg
    Local $aID = StringRegExp($vMsg, '^.*№(\d+).*$', 1)
   
    If IsArray($aID) Then
        GUICtrlCreateListViewItem($vMsg & '|' & $sRetTxt, $ListViewIn)
        _GUICtrlListView_EnsureVisible($ListViewIn, _GUICtrlListView_GetItemCount($ListViewIn) - 1)
    EndIf
   
    Return $sRetTxt ; Возвращаетм ответ отправителю
EndFunc


У меня тут библиотека подключается от пути на два уровня выше, т.к там у меня версия 0.3.
 
Последнее редактирование:
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 472
Репутация
2 402
С версией 0.4 тут есть глобальная проблема, дело в том что свойство Data у объекта не уникально, из за этого и конфликт, а чтобы сделать его уникальным, нам нужна функция Assign для объектов, а этого как известно у нас в AutoIt'е нет.
Будем думать...
 

Webarion

Знающий
Сообщения
83
Репутация
5
И зачем в примере WM_COMMAND?
Кнопка Стоп, не срабатывала, видимо из за времени обработки и большого Sleep, решил через WM_COMMAND
Сообщение автоматически объединено:

Вот мой вариант:
Хороший вариант
 
Верх