Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   AutoIt (http://forum.oszone.net/forumdisplay.php?f=103)
-   -   [решено] Внутренняя связь между двумя "файлами" написанных на AutoIT (http://forum.oszone.net/showthread.php?t=140252)

FlatX007 15-05-2009 21:10 1119589

Внутренняя связь между двумя "файлами" написанных на AutoIT
 
Допустим есть 2 утилиты выполняющие некоторые функции ... как можно сделать связь между ними , то есть одна программа получает данные а другая отображает. Через чтение и запись INI файла очень неустраивает!!
Нужна "связь" неоставляющая видимых следов :)

Мона как нито ? ...

beve 15-05-2009 21:38 1119617

Как один из вариантов (если обе утилитки написанны на Autoit), можно сделать невидимый контрол в одной из утилиток (или у двоих), например Edit, и потом просто отсылать в него сообщения, и соответственно Через соответствующую функцию отслеживать "приходящие сообщения".

Yashied 15-05-2009 21:39 1119618

Цитата:

Цитата FlatX007
Допустим есть 2 утилиты выполняющие некоторые функции ... как можно сделать связь между ними , то есть одна программа получает данные а другая отображает. Через чтение и запись INI файла очень неустраивает!!
Нужна "связь" неоставляющая видимых следов »

Например с помощью WM_COPYDATA. Подойдет?

Вот тебе пример. Откомпилируй его и запусти EXE-файл два раза.

Код:

#Include <GUIConstantsEx.au3>

Opt('WinTitleMatchMode', 3)

global const $TITLE_SENDER = '#Sender'
global const $TITLE_RECEIVER = '#Reseiver'
global const $WM_COPYDATA = 0x004A

global $sMsg, $Dummy, $Flag = 0

if WinExists($TITLE_RECEIVER) then
    if
WinExists($TITLE_SENDER) then
        exit
    endif

    _Sender()
else
    _Receiver()
endif

func
_Sender()

    local $Input, $Button, $ID

    GUICreate($TITLE_SENDER, 400, 100)
    $Input = GUICtrlCreateinput('', 20, 20, 360, 20)
    $Button = GUICtrlCreateButton('Send', 165, 60, 70, 23)
    $Dummy = GUICtrlCreateDummy()
    GUIRegisterMsg($WM_COPYDATA, '_WM_COPYDATA')
    GUISetState()

    while 1
        $ID = GUIGetMsg()
        switch $ID
            case 0
                continueloop
            case
$GUI_EVENT_CLOSE
                _SendData(WinGetHandle($TITLE_RECEIVER), '@exit')
                exitloop
            case
$Button
                $sMsg
= GUICtrlRead($Input)
                $hWnd = WinGetHandle($TITLE_RECEIVER)
                if (not @error) and ($sMsg > '') then
                    if
_SendData($hWnd, $sMsg) then
                        GUICtrlSetState($Button, $GUI_DISABLE)
                    endif
                endif
            case $Dummy
                GUICtrlSetState($Button, $GUI_ENABLE)
        endswitch
    wend

    GUIDelete()
endfunc

func _Receiver()
    GUICreate($TITLE_RECEIVER)
    GUIRegisterMsg($WM_COPYDATA, '_WM_COPYDATA')

    while 1
        Sleep(10)
        if $Flag then
            if $sMsg = '@exit' then
                exitloop
            endif
            $Flag = 0
            _DoSomething($sMsg)
            _SendData(WinGetHandle($TITLE_SENDER), '')
        endif
    wend

    GUIDelete()
endfunc; _Receiver

func _DoSomething($sData)
    MsgBox(0, 'Message', $sData)
endfunc; _DoSomething

func _SendData($hWnd, $sData)

    local $tCOPYDATA, $tMsg

    $tMsg = DllStructCreate('char[' & StringLen($sData) + 1 & ']')
    DllStructSetData($tMsg, 1, $sData)
    $tCOPYDATA = DllStructCreate('dword;dword;ptr')
    DllStructSetData($tCOPYDATA, 2, StringLen($sData) + 1)
    DllStructSetData($tCOPYDATA, 3, DllStructGetPtr($tMsg))
    $Ret = DllCall('user32.dll', 'lparam', 'SendMessage', 'hwnd', $hWnd, 'int', $WM_COPYDATA, 'wparam', 0, 'lparam', DllStructGetPtr($tCOPYDATA))
    if (@error) or ($Ret[0] = -1) then
        return 0
    endif
    return 1
endfunc; _SendData

func _WM_COPYDATA($hWnd, $msgID, $wParam, $lParam)

    local $tCOPYDATA = DllStructCreate('dword;dword;ptr', $lParam)
    local $tMsg = DllStructCreate('char[' & DllStructGetData($tCOPYDATA, 2) & ']', DllStructGetData($tCOPYDATA, 3))

    $sMsg = DllStructGetData($tMsg, 1)

; For Sender
    GUICtrlSendToDummy($Dummy)

; For Receiver
    $Flag = 1

    return 0
endfunc; _WM_COPYDATA


proxy 15-05-2009 23:41 1119691

Или попробуйте эту udf - можно создать внешний ассоциируемый массив, который может использовать оба скрипта.
К примеру, если скрипт1 запускает скрипт2 то он может передовать указатель "этого" массива, и все будет ок.

Либо как сказал beve.
Скрытые элемнты, и каждые 10-20 vctr считывать из них данные. По анализу данных выполнять необходимые действия.

Yashied 15-05-2009 23:58 1119695

Цитата:

Цитата proxy
Или попробуйте эту udf - можно создать внешний ассоциируемый массив, который может использовать оба скрипта.
К примеру, если скрипт1 запускает скрипт2 то он может передовать указатель "этого" массива, и все будет ок. »

Ну это уже совсем экзотика, к тому же написан на COM. Проще тогда уж использовать STDIN и STDOUT. А чем WM_COPYDATA не устраивает, большинство програм так общаются.

Yashied 16-05-2009 00:16 1119705

Вот еще один пример. Messages.au3 можешь скачать здесь.

Код:

#Include <EditConstants.au3>
#Include <GUIConstantsEx.au3>
#Include <GUIEdit.au3>
#Include <GUISlider.au3>
#Include <StaticConstants.au3>
#Include <WindowsConstants.au3>

#Include <Messages.au3>

#NoTrayIcon

if StringLower(StringRight(@ScriptFullPath, 3)) = 'au3' then
    MsgBox(64, 'Messages UDF Library Demonstration', 'To run this script, you must first compile it and then run the (.exe) file.')
    exit
endif


Opt('MustDeclareVars', 1)

if $CmdLine[0] = 0 then
    ShellExecute(@ScriptFullPath, '1')
    ShellExecute(@ScriptFullPath, '2')
    ShellExecute(@ScriptFullPath, '3')
    exit
endif

local
$Form, $Input1, $Input2, $Radio1, $Radio2, $Radio3, $ButtonSend, $Edit, $Slider, $Check

switch $CmdLine[1]
    case '1', '2', '3'
        _Main(Int($CmdLine[1]))
    case else

endswitch

func
_Main($Index)

    local $GUIMsg, $nScript, $Data, $Timer = _MsgTimerInterval(0)

    $Form = GUICreate('Script' & $Index, 324, 384, (@DesktopWidth - 1018) / 2 + ($Index - 1) * 344, (@DesktopHeight - 440) / 2, BitOR($WS_CAPTION, $WS_SYSMENU), $WS_EX_TOPMOST)

    GUISetFont(8.5, 400, 0, 'Tahoma', $Form)

    GUICtrlCreateLabel('Message:', 14, 22, 48, 14)
    $Input1 = GUICtrlCreateInput('', 64, 19, 246, 20)
    GUICtrlCreateLabel('Send to:', 14, 56, 48, 14)

    GUIStartGroup()

    $Radio1 = GUICtrlCreateRadio('Script1', 64, 56, 56, 14)
    GUICtrlSetState(-1, $GUI_CHECKED)
    $Radio2 = GUICtrlCreateRadio('Script2', 130, 56, 56, 14)
    $Radio3 = GUICtrlCreateRadio('Script3', 196, 56, 56, 14)

    $ButtonSend = GUICtrlCreateButton('Send', 236, 88, 75, 23)
    GUICtrlSetState(-1, $GUI_DEFBUTTON)
    GUICtrlCreateLabel('', 14, 128, 299, 2, $SS_ETCHEDHORZ)
    GUICtrlCreateLabel('Received message:', 14, 142, 98, 14)
    $Edit = GUICtrlCreateEdit('', 14, 160, 296, 129, BitOR($ES_READONLY, $WS_VSCROLL, $WS_HSCROLL))
    GUICtrlSetBkColor(-1, 0xFFFFFF)
    GUICtrlCreateLabel('Timer interval (ms):', 14, 316, 98, 14)
    $Slider = GUICtrlCreateSlider(110, 312, 162, 26, BitOR($TBS_AUTOTICKS, $WS_TABSTOP))
    GUICtrlSetLimit(-1, 20, 1)
    GUICtrlSetData(-1, $Timer / 50)
    _GUICtrlSlider_SetTicFreq(-1, 1)
    $Input2 = GUICtrlCreateInput($Timer, 274, 313, 36, 20, $ES_READONLY)
    GUICtrlSetBkColor(-1, 0xFFFFFF)
    $Check = GUICtrlCreateCheckBox('Enable receiver', 14, 354, 96, 19)
    GUICtrlSetState(-1, $GUI_CHECKED)

    Opt('GUICloseOnESC', 0)

    GUISetState()

    _MsgRegister('Script' & $Index, '_Receiver')

    while 1
        $GUIMsg = GUIGetMsg()
        select
            case
$GUIMsg = $GUI_EVENT_CLOSE
                exit
            case
$GUIMsg = $ButtonSend
                for $i = $Radio1 to $Radio3
                    if GUICtrlRead($i) = $GUI_CHECKED then
                        $nScript = 1 + $i - $Radio1
                        exitloop
                    endif
                next
                $Data = GUICtrlRead($Input1)
                if StringStripWS($Data, 3) = '' then
                    $Data = '(empty)'
                endif
                if _IsReceiver('Script' & $nScript) then
                    _MsgSend('Script' & $nScript, 'From Script' & $Index & ':  ' & $Data)
                endif
            case $GUIMsg = $Slider
                _MsgTimerInterval($Timer)
            case $GUIMsg = $Check
                if GUICtrlRead($Check) = $GUI_CHECKED then
                    GUICtrlSetState($Edit, $GUI_ENABLE)
                    GUICtrlSetBkColor($Edit, 0xFFFFFF)
                    GUICtrlSetState($Slider, $GUI_ENABLE)
                    GUICtrlSetState($Input2, $GUI_ENABLE)
                    _MsgRegister('Script' & $Index, '_Receiver')
                else
                    GUICtrlSetState($Edit, $GUI_DISABLE)
                    GUICtrlSetBkColor($Edit, $GUI_BKCOLOR_TRANSPARENT)
                    GUICtrlSetState($Slider, $GUI_DISABLE)
                    GUICtrlSetState($Input2, $GUI_DISABLE)
                    _MsgRegister('Script' & $Index, '')
                endif
        endselect
        $Data = GUICtrlRead($Slider) * 50
        if BitXOR($Data, $Timer) then
            $Timer = $Data
            GUICtrlSetData($Input2, $Timer)
        endif
    wend
endfunc; _Main

func _Receiver($sMessage)
    _GUICtrlEdit_AppendText($Edit, $sMessage & @CRLF)
    return 0
endfunc; _Receiver


FlatX007 16-05-2009 00:31 1119721

Цитата:

Цитата Yashied
Например с помощью WM_COPYDATA. Подойдет?
Вот тебе пример. Откомпилируй его и запусти EXE-файл два раза. »

Типа в одно GUI вводим текст а другой "GUI" его отображает ?
А как в краце это работает для чего какая функция ?

Yashied 16-05-2009 00:55 1119733

Одно окно посылает сообщение WM_COPYDATA другому. В параметрах сообщения передаешь свои данные. Окно-приемник получает это сообщение через зарегистрированную функцию GUIRegisterMsg(). Обратно прердача идет анологичным образом.

Yashied 16-05-2009 02:06 1119763

FlatX007, постараюсь объяснить на примере моего UDF. Вот простой пример программы-приемника:

Код:

#Include <Messages.au3>

Global $MyMessage = ''

_MsgRegister('Receiver', '_Receiver')

While 1
    Sleep(10)
; Проверяем наличие сообщения
    If $MyMessage > '' Then
; Здесь выполняем произвольный код, сообщение находится в переменной $MyMessage
        MsgBox(0, '', $MyMessage)
; Очищаем сообщение
        $MyMessage = ''
    EndIf
WEnd

Func
_Receiver($sData)
    $MyMessage = $sData
    Return 0
EndFunc; _Receiver

Первым делом регистрируешь функцию для приема сообщений, здесь я ее назвал _Receiver(). Первый параметр - это произвольное (уникальное) имя, на твое усмотрение.

Код:

_MsgRegister('Receiver', '_Receiver')
Далее в цикле проверяешь наличие нового сообщения. Как только сообщение будет получено ($MyMessage > ''), выполняешь необходимые действия и очищаешь сообщение ($MyMessage = ''). Надеюсь понимаешь для чего это нужно. Функция-приемник (_Receiver()) выполняется, когда приходят сообщения. Она просто передает переменной $MyMessage данные, которые ей были переданы. Для передачи сообщения из другого скрипта просто пишешь следующее:

Код:

_MsgSend('Receiver', 'Текст сообщения')
Здесь первый параметр должен в точности соответствовать первому параметру у функции _MsgRegister(). Это идентификатор твоего приемника. Вот и все. Конечно, правильнее будет организовать передачу в дуплексном режиме. Например: приемник получает очередное сообщение обрабатывает его и в ответ посылает ответное сообщение, мол все OK, давай дальше. И только после этого ты посылаешь следующее сообщение, и т.д. Описание других функций из этого UDF можешь прочесть в самом файле. Все, пойду спать, устал.

:gulp:

Creat0R 16-05-2009 11:10 1119871

Ох этих методов море развелось, вот ещё пару:

* AddControls_Interaction.zip - Добавление новых элементов с внешнего скрипта.
* UDF - «AU3_INTERACT.au3» (второй пример) - Удобная интеракция между скриптами через сообщения (SendMessage).

Yashied 16-05-2009 16:29 1120110

Самый простой способ. Открой Receiver.au3 в SciTE и запусти его.


Sender.au3

Код:

$i = 0
While 1
    Sleep(500)
    $i += 1
    ConsoleWrite(String($i))
WEnd


Receiver.au3

Код:

#Include <Constants.au3>
#Include <File.au3>

Const $AutoIt = RegRead('HKLM\SOFTWARE\AutoIt v3\AutoIt', 'InstallDir') & '\Aut2Exe\Aut2exe.exe'
Const $Script1Au3 = 'Sender.au3'
Const $Script1Exe = _TempFile(@TempDir, '~', '.exe')

Local $Pid, $Data

RunWait($AutoIt & ' /in ' & $Script1Au3 & ' /out ' & $Script1Exe)
$Pid = Run($Script1Exe, '', @SW_SHOW, $STDOUT_CHILD)

While 1
    $Data = StdoutRead($Pid)
    If $Data <> '' Then
        ConsoleWrite($Data & @CR)
    EndIf
    If
@error Then
        ExitLoop
    EndIf
WEnd


ProcessWaitClose($Pid)
FileDelete($Script1Exe)


FlatX007 16-05-2009 20:58 1120302

Ой как много всего панаписали .... я ещё даж не начал разбираться :)


Время: 14:18.

Время: 14:18.
© OSzone.net 2001-