PDA

Показать полную графическую версию : [решено] Внутренняя связь между двумя "файлами" написанных на AutoIT


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

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

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

Yashied
15-05-2009, 21:39
Допустим есть 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
Или попробуйте эту udf (http://www.autoitscript.com/forum/index.php?showtopic=70955&hl=hash.au3&st=0)- можно создать внешний ассоциируемый массив, который может использовать оба скрипта.
К примеру, если скрипт1 запускает скрипт2 то он может передовать указатель "этого" массива, и все будет ок.

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

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

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

Yashied
16-05-2009, 00:16
Вот еще один пример. Messages.au3 можешь скачать здесь (http://www.autoitscript.com/forum/index.php?showtopic=91346).

#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
Например с помощью WM_COPYDATA. Подойдет?
Вот тебе пример. Откомпилируй его и запусти EXE-файл два раза. »

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

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

Yashied
16-05-2009, 02:06
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
Ох этих методов море развелось, вот ещё пару:

* AddControls_Interaction.zip (http://creator-lab.ucoz.ru/AutoIt/AddControls_Interaction.zip) - Добавление новых элементов с внешнего скрипта.
* UDF - «AU3_INTERACT.au3» (http://forum.ru-board.com/topic.cgi?forum=5&topic=17705&start=1440#6) (второй пример) - Удобная интеракция между скриптами через сообщения (SendMessage).

Yashied
16-05-2009, 16:29
Самый простой способ. Открой 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
Ой как много всего панаписали .... я ещё даж не начал разбираться :)




© OSzone.net 2001-2012