Что нового

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

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,662
Репутация
2,461
Версия 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
Источник
Ссылка на источник

Вложения

  • AppInteract_v0.1.zip
    3.3 КБ · Просмотры: 6
  • AppInteract_v0.2.zip
    4 КБ · Просмотры: 2
  • AppInteract_v0.3.zip
    5.4 КБ · Просмотры: 3
  • AppInteract_v0.4.zip
    9.3 КБ · Просмотры: 1
  • AppInteract_v0.5.zip
    9.8 КБ · Просмотры: 6
Последнее редактирование:

Webarion

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

CreatoR

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

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

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

Webarion

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

CreatoR

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

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

Webarion

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

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

CreatoR

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

Запускаем получатель первым:
Код:
#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,662
Репутация
2,461
По идее вот так должно было бы сработать:

Код:
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,662
Репутация
2,461
Обновление:

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

Webarion

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

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

CreatoR

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

Webarion

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

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,662
Репутация
2,461
Это всё можно устроить внутри скрипта и не обязательно вешать на библиотеку, т.к её функция отправлять и получать данные, не более.
Тут нужно организовать грамотную очередь и обработку.

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

CreatoR

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

Вложения

  • AO Version.zip
    44.6 КБ · Просмотры: 2

Webarion

Знающий
Сообщения
105
Репутация
10
Тествовый скрипт под новую версию:
Код:
#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,662
Репутация
2,461
С версией 0.3 данный пример работает хорошо.
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,662
Репутация
2,461
И зачем в примере 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,662
Репутация
2,461
С версией 0.4 тут есть глобальная проблема, дело в том что свойство Data у объекта не уникально, из за этого и конфликт, а чтобы сделать его уникальным, нам нужна функция Assign для объектов, а этого как известно у нас в AutoIt'е нет.
Будем думать...
 

Webarion

Знающий
Сообщения
105
Репутация
10
И зачем в примере WM_COMMAND?

Кнопка Стоп, не срабатывала, видимо из за времени обработки и большого Sleep, решил через WM_COMMAND
Сообщение автоматически объединено:

Вот мой вариант:

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