Что нового

Передача строки из скрипта в с скрипт

Нубокодер

Новичок
Сообщения
75
Репутация
0
В скриптах источник_1.ехе, источник_2.ехе, источник_3.ехе генерируются случайные числа (от 0 до 99) в случайном промежутке времени (от 1 до 3 секунд). Нужно передавать текущие значения этих чисел каждую секунду в виде строк в скрипт приемник.au3 и выводить (Передавать нужно обязательно строковый тип данных). Помогите пожалуйста. Покажите как это сделать. На форуме нашел только слишком сложные или не подходящие примеры. Неужели нет простого способа передать строку данных из одного скрипта в другой?

источник_1.au3:
Код:
#include <GUIConstantsEx.au3>

GUICreate("1-ый источник:", 215, 23, 5, 5)
GUISetState()
Opt("GUIOnEventMode", 1)  ; Включает режим OnEvent (по событию)
GUISetOnEvent($GUI_EVENT_CLOSE, "_CLOSEClicked") ; обработка закрытия

$data = "??.??" ; начальное значение неизвестно

While 1

  $data_1 = Round(Random(99), 2) ; случайное число от 0 до 99
  Sleep(1000 * Round(Random(1, 3), 0)) ; случайная задержка от 1 до 3 сек.
  $data_1 = "Значение с 1-го источника = " & $data_1
  $ID_1 = GUICtrlCreateLabel( $data_1, 15, 5)

  ConsoleWrite ($data_1 & @CRLF)
WEnd

Func _CLOSEClicked()
  $ext = MsgBox(4, "Выход", "Вы уверены, что хотите выйти?")
  If $ext = 6 Then Exit
  Return
EndFunc

источник_2.au3:
Код:
#include <GUIConstantsEx.au3>

GUICreate("2-ой источник:", 215, 23, 5, 65)
GUISetState()
Opt("GUIOnEventMode", 1)  ; Включает режим OnEvent (по событию)
GUISetOnEvent($GUI_EVENT_CLOSE, "_CLOSEClicked") ; обработка закрытия

$data = "??.??" ; начальное значение неизвестно

While 1

  $data_2 = Round(Random(99), 2) ; случайное число от 0 до 99
  Sleep(1000 * Round(Random(1, 3), 0)) ; случайная задержка от 1 до 3 сек.
  $data = "Значение с 2-го источника = " & $data_2
  $ID_2 = GUICtrlCreateLabel( $data, 15, 5)

  ConsoleWrite ($data & @CRLF)
WEnd

Func _CLOSEClicked()
  $ext = MsgBox(4, "Выход", "Вы уверены, что хотите выйти?")
  If $ext = 6 Then Exit
  Return
EndFunc

источник_3.au3:
Код:
#include <GUIConstantsEx.au3>

GUICreate("3-ий источник:", 215, 23, 5, 125)
GUISetState()
Opt("GUIOnEventMode", 1)  ; Включает режим OnEvent (по событию)
GUISetOnEvent($GUI_EVENT_CLOSE, "_CLOSEClicked") ; обработка закрытия

$data = "??.??" ; начальное значение неизвестно

While 1

  $data_3 = Round(Random(99), 2) ; случайное число от 0 до 99
  Sleep(1000 * Round(Random(1, 3), 0)) ; случайная задержка от 1 до 3 сек.
  $data = "Значение с 3-го источника = " & $data_3
  $ID_3 = GUICtrlCreateLabel( $data, 15, 5)

  ConsoleWrite ($data & @CRLF)
WEnd

Func _CLOSEClicked()
  $ext = MsgBox(4, "Выход", "Вы уверены, что хотите выйти?")
  If $ext = 6 Then Exit
  Return
EndFunc

приемник.au3:
Код:
#include <GUIConstantsEx.au3>

GUICreate("приемник:", 215, 69, 237, 43)
GUISetState()
Opt("GUIOnEventMode", 1)  ; Включает режим OnEvent (по событию)
GUISetOnEvent($GUI_EVENT_CLOSE, "_CLOSEClicked") ; обработка закрытия

$data_1 = "??.??" ; начальное значение неизвестно
$data_2 = "??.??" ; начальное значение неизвестно
$data_3 = "??.??" ; начальное значение неизвестно

While 1

  Sleep(1000 * 1) ; задержка 1 сек.

;~   ТУТ НУЖНО КАЖДУЮ СЕКУНДУ ПРИНИМАТЬ ТЕКУЩИЕ СТРОКОВЫЕ ЗНАЧЕНИЯ ИЗ СКРИПТОВ:
;~   источник_1.ехе, источник_2.ехе, источник_3.ехе
;~   И ВЫВОДИТЬ В КОНСОЛЬ. КАК ЭТО СДЕЛАТЬ?!


  $ID_Out_1 = GUICtrlCreateLabel( "Значение с 1-го источника = " & $data_1, 15, 5)
  $ID_Out_2 = GUICtrlCreateLabel( "Значение с 2-го источника = " & $data_2, 15, 28)
  $ID_Out_3 = GUICtrlCreateLabel( "Значение с 3-го источника = " & $data_3, 15, 51)
;~   ConsoleWrite ($data & @CRLF)
WEnd

Func _CLOSEClicked()
  $ext = MsgBox(4, "Выход", "Вы уверены, что хотите выйти?")
  If $ext = 6 Then Exit
  Return
EndFunc
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Примеров было целый вагон. Поищите по слову "WM_COPYDATA".
 

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
Поищите по слову "WM_COPYDATA".
думаю, что и это будет "сложным и неподходящим"
Нубокодер
нужно понять не пример а принцип. самым простым и , на мой взгляд, лучшим считаю способ описанный в справке к 3.3.12.0
Код:
_WinAPI_CreateFileMapping

с правке есть пример. раздели на скрипты и дело сделано
 

InnI

AutoIT Гуру
Сообщения
4,912
Репутация
1,429
Нубокодер
Неужели нет простого способа передать строку данных
Есть. При помощи INI-файла. Каждый "источник" пишет в свою секцию значение, а "приёмник" читает из соответствующих секций.
 
Автор
Нубокодер

Нубокодер

Новичок
Сообщения
75
Репутация
0
Yashied сказал(а):
Примеров было целый вагон. Поищите по слову "WM_COPYDATA".
Поискал и с горя офигел: структуры, объекты, контейнеры, карты файлов, ини файлы!!! и все это в сопровождении десятков ошибок и общения в стиле: "это вот так" - "нет это вот так" - "хотя можно попробовать и так, но в новой версии вряд ли". Я же новичок и в такой информации как в болоте тону.)) Для этого и создал простейший пример, чтоб Вы могли спокойно сами выбрать наиболее подходящий метод для конкретной задачи и наглядно показать решение. Мне всего лишь одну строчку надо максимально быстро передавать из одного скрипта в другой (НЕ подойдет только медленный метод чтения-записи через файл).
 

C2H5OH

AutoIT Гуру
Сообщения
1,473
Репутация
333
imho, самый подходящий способ - это
Код:
TCPSend
TCPRecv


Но! В версии AutoIt 3.3.12.0 в функция TCPRecv работает не совсем корректно - считает ошибкой получение пустой строки.
Ошибка эта зафиксирована, её обещают исправить в следующей версии AutoIt, но когда выйдет эта следующая версия никто не знает.

На самом деле эта ошибка легко обходится, но если Вы в такой информации тонете как в болоте...
Лучше передавайте через файл.
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
C2H5OH , если не предполагается сетевая передача данных, то данный способ является наихудшим вариантом.
 

C2H5OH

AutoIT Гуру
Сообщения
1,473
Репутация
333
Yashied, ну, это кому как нравится.
Если следовать стилю ТС, то ему, наверное, проще было бы сразу читать значения из GUI источников.

Источник 1
Код:
#include <GUIConstantsEx.au3>

GUICreate("1-ый источник:", 215, 23, 5, 5)
GUISetState()
Opt("GUIOnEventMode", 1)  ; Включает режим OnEvent (по событию)
GUISetOnEvent($GUI_EVENT_CLOSE, "_CLOSEClicked") ; обработка закрытия

$data_1 = "??.??" ; начальное значение неизвестно
$ID_1 = GUICtrlCreateLabel( $data_1, 15, 5)
While 1

  $data_1 = Round(Random(99), 2) ; случайное число от 0 до 99
  Sleep(1000 * Round(Random(1, 3), 0)) ; случайная задержка от 1 до 3 сек.
  GUICtrlSetData($ID_1, $data_1)

  ConsoleWrite ($data_1 & @CRLF)
WEnd

Func _CLOSEClicked()
  $ext = MsgBox(4, "Выход", "Вы уверены, что хотите выйти?")
  If $ext = 6 Then Exit
  Return
EndFunc

Приёмник
Код:
#include <GUIConstantsEx.au3>

GUICreate("приемник:", 215, 69, 237, 43)
GUISetState()
Opt("GUIOnEventMode", 1)  ; Включает режим OnEvent (по событию)
GUISetOnEvent($GUI_EVENT_CLOSE, "_CLOSEClicked") ; обработка закрытия

$data_1 = "??.??" ; начальное значение неизвестно
$data_2 = "??.??" ; начальное значение неизвестно
$data_3 = "??.??" ; начальное значение неизвестно

$ID_Out_1 = GUICtrlCreateLabel( "Значение с 1-го источника = " & $data_1, 15, 5)

While 1

  Sleep(1000 * 1) ; задержка 1 сек.

  $data_1 = ControlGetText("1-ый источник:","", "[CLASS:Static; INSTANCE:1]")

  GUICtrlSetData( $ID_Out_1, "Значение с 1-го источника = " & $data_1)
  ConsoleWrite ($data_1 & @CRLF)
WEnd

Func _CLOSEClicked()
  $ext = MsgBox(4, "Выход", "Вы уверены, что хотите выйти?")
  If $ext = 6 Then Exit
  Return
EndFunc

Вот такой изврат...
 
Автор
Нубокодер

Нубокодер

Новичок
Сообщения
75
Репутация
0
Код:
_WinAPI_CreateFileMapping

с правке есть пример. раздели на скрипты и дело сделано
С удовольствием бы почитал, но по ссылке выдает ошибку. И в моей оффлайн-справке почему то этой функции нет.

C2H5OH сказал(а):
Вот такой изврат...
Но ведь это единственный рабочий пример в топике и какой оригинально-элементарный.))
Правда он тоже не подойдет, если только на первое время, чтобы работала прога ну хоть как-нибудь, пока я докапапываюсь до более сложных способов.
 

Garrett

Модератор
Локальный модератор
Сообщения
3,999
Репутация
967

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Нубокодер, вот пример использования WM_COPYDATA. Данный способ является самым распространенным и применяется для передачи практически любых данных между окнами процесса(ов). Для справки, любое приложение Windows, если оно не является консольным, имеет как минимум одно окно (либо скрытое, либо нет). Сама передача данных осуществляется посредством специальной структуры COPYDATASTRUCT. Более подробно о структурах можно почитать здесь. Итак, записываем эту структуру как есть в AutoIt:

Код:
Global Const $tagCOPYDATASTRUCT = 'ulong_ptr dwData;dword cbData;ptr lpData'


где

dwData - 32- или 64-битное беззнаковое целое число, которое будет передано в окно-приемник.
cbData - размер блока данных в байтах, на который ссылается параметр lpData (см. ниже).
lpData - адрес блока данных для передачи в окно-приемник.

Таким образом мы можем передавать как произвольные данные при помощи lpData, например строки, так и просто целые числа через параметр dwData. Как вариант, можно задействовать и оба параметра, но в этом как правило нет необходимости. Непосредственно сама передача данных осуществляется с помощью сообщения WM_COPYDATA:

Код:
$aResult = DllCall('user32.dll', 'bool', 'SendMessage', 'hwnd', $hWnd, 'uint', $WM_COPYDATA, 'hwnd', 0, 'struct*', $tCOPYDATASTRUCT)
If (@Error) Or (Not $aResult[0]) Then
	; Ошибка
EndIf


где

$hWnd - Хэндл окна-приемника, для которого предназначено данное сообщение.
$tCOPYDATASTRUCT - Структура COPYDATASTRUCT, содержащая необходимые данные для передачи.

При успешном получении данных обработчик окна-приемника (см. ниже) должен возвратить 1, что и будет содержаться в $aResult[0]. Если сообщение будет передано несуществующему окну, то $aResult[0] будет содержать 0, что можно классифицировать как ошибку (по ситуации). Таким образом, чтобы передать данные другому окну, необходимо выполнить следующие действия:
  • Создать структуру COPYDATASTRUCT.
  • Заполнить структуру данными, которые должны быть переданы в окно-приемник.
  • Передать сообщение WM_COPYDATA.
  • Проверить наличие ошибки (если необходимо).
Переваривая все выщесказанное и исходя из вашей задачи, можно написать следующую функцию:

Код:
#Include <APIConstants.au3>

Global Const $tagCOPYDATASTRUCT = 'ulong_ptr dwData;dword cbData;ptr lpData'

_SendMsg('Нубокодер_Приемник', 1, '99.99') ; Передаем строку "99.99" из источника 1 (см. второй параметр)

Func _SendMsg($hWnd, $iData, $sData = '')

	Local $tCOPYDATASTRUCT = DllStructCreate($tagCOPYDATASTRUCT)
	Local $iLength = StringLen($sData)
	Local $tText, $aResult

	If Not IsHWnd($hWnd) Then
		$hWnd = WinGetHandle($hWnd)
	EndIf
	$tCOPYDATASTRUCT.dwData = $iData
	If $iLength Then
		$tText = DllStructCreate('wchar Text[' & ($iLength + 1) & ']')
		$tText.Text = $sData
		$tCOPYDATASTRUCT.cbData = DllStructGetSize($tText)
		$tCOPYDATASTRUCT.lpData = DllStructGetPtr($tText)
	Else
		$tCOPYDATASTRUCT.cbData = 0
		$tCOPYDATASTRUCT.lpData = Null
	EndIf
	$aResult = DllCall('user32.dll', 'bool', 'SendMessage', 'hwnd', $hWnd, 'uint', $WM_COPYDATA, 'hwnd', Null, 'struct*', $tCOPYDATASTRUCT)
	If (@Error) Or (Not $aResult[0]) Then
		Return SetError(1, 0, 0)
	EndIf
	Return 1
EndFunc   ;==>_SendMsg


Для того, чтобы окно-приемник (в данном случае окно с заголовком "Нубокодер_Приемник"), могло принимать сообщения, необходимо написать и зарегистрировать обработчик WM_COPYDATA, который будет получать структуру COPYDATASTRUCT и считывать из нее необходимые данные:

Код:
#Include <APIConstants.au3>

Global Const $tagCOPYDATASTRUCT = 'ulong_ptr dwData;dword cbData;ptr lpData'

$hReceiver = GUICreate('Нубокодер_Приемник')
GUIRegisterMsg($WM_COPYDATA, 'WM_COPYDATA')

While 1
	Sleep(1000)
WEnd

Func WM_COPYDATA($hWnd, $iMsg, $wParam, $lParam)
	Switch $hWnd
		Case $hReceiver

			Local $tCOPYDATASTRUCT = DllStructCreate($tagCOPYDATASTRUCT, $lParam)
			Local $tText = DllStructCreate('wchar szData[' & ($tCOPYDATASTRUCT.cbData / 2) & ']', $tCOPYDATASTRUCT.lpData)

			ConsoleWrite('Сообщение от источника ' & $tCOPYDATASTRUCT.dwData & ': ' & $tText.szData & @CRLF)
			Return 1
	EndSwitch
	Return 0
EndFunc   ;==>WM_COPYDATA


Обратите внимание, что заголовок окна в источнике и приемнике должен быть одинаковый и уникальный. В противном случае сообщение может уйти другому окну с таким же названием (если есть).

P.S

Как все это проверить? Запустите второй скрипт (приемник) из SciTE, т.к. он пишет в консоль. Затем запускайте первый скрипт (передатчик) и наслаждайтесь результатом.

P.S.S

Код написан для AutoIt 3.3.12.0.
 
Автор
Нубокодер

Нубокодер

Новичок
Сообщения
75
Репутация
0
Огромное спасибо за подробную и не очень информацию. Буду разбираться и применять, применять, применять. :laugh:
 

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
[?]
Для этого и создал простейший пример, чтоб Вы могли спокойно сами выбрать наиболее подходящий метод для конкретной задачи и наглядно показать решение.
OffTopic:
просто перл, а не предложение.
 
Верх