Показать полную графическую версию : [решено] Внутренняя связь между двумя "файлами" написанных на AutoIT
FlatX007
15-05-2009, 21:10
Допустим есть 2 утилиты выполняющие некоторые функции ... как можно сделать связь между ними , то есть одна программа получает данные а другая отображает. Через чтение и запись INI файла очень неустраивает!!
Нужна "связь" неоставляющая видимых следов :)
Мона как нито ? ...
Как один из вариантов (если обе утилитки написанны на Autoit), можно сделать невидимый контрол в одной из утилиток (или у двоих), например Edit, и потом просто отсылать в него сообщения, и соответственно Через соответствующую функцию отслеживать "приходящие сообщения".
Допустим есть 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
Или попробуйте эту udf (http://www.autoitscript.com/forum/index.php?showtopic=70955&hl=hash.au3&st=0)- можно создать внешний ассоциируемый массив, который может использовать оба скрипта.
К примеру, если скрипт1 запускает скрипт2 то он может передовать указатель "этого" массива, и все будет ок.
Либо как сказал beve.
Скрытые элемнты, и каждые 10-20 vctr считывать из них данные. По анализу данных выполнять необходимые действия.
Или попробуйте эту udf - можно создать внешний ассоциируемый массив, который может использовать оба скрипта.
К примеру, если скрипт1 запускает скрипт2 то он может передовать указатель "этого" массива, и все будет ок. »
Ну это уже совсем экзотика, к тому же написан на COM. Проще тогда уж использовать STDIN и STDOUT. А чем WM_COPYDATA не устраивает, большинство програм так общаются.
Вот еще один пример. 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" его отображает ?
А как в краце это работает для чего какая функция ?
Одно окно посылает сообщение WM_COPYDATA другому. В параметрах сообщения передаешь свои данные. Окно-приемник получает это сообщение через зарегистрированную функцию GUIRegisterMsg(). Обратно прердача идет анологичным образом.
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:
Ох этих методов море развелось, вот ещё пару:
* 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).
Самый простой способ. Открой 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
vBulletin v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.