talk() - Interscript communication auch bidirektional ?

Stelle Fragen zur Programmierung mit Autohotkey

Moderator: jNizM

effel
Posts: 544
Joined: 16 Jan 2018, 13:34

talk() - Interscript communication auch bidirektional ?

Post by effel » 08 Jul 2020, 11:28

hallo, ich habe im alten Forum diese https://autohotkey.com/board/topic/94321-talk-interscript-communication-provider-and-more/ Funktion von @aviaryan gefunden, nach einem abendfüllenden Versuch die Variable bidirektional auszutauschen, möchte ich hier fragen, geht das auch in beide Richtungen?

unten die drei Scripte veranschaulichen den Effekt.

`eins` sendet eine Variable mit wechselndem Inhalt, die von `zwei` (automatisch) und `drei` (mit F10) gleichzeitig empfangen wird.

cool wäre, wenn ich ein busy Signal an `eins` senden könnte

Code: Select all

/*
; https://github.com/aviaryan/autohotkey-scripts/blob/master/Functions/talk.ahk
; https://pastebin.com/NsRdXCcj
; https://autohotkey.com/board/topic/94321-talk-interscript-communication-provider-and-more/page-3
########################
talk v0.6			   #
by Avi Aryan		   #
##################################
Thanks to Autohotkey help file   #
================================ #
Licensed Under MIT License	     #
##################################
Points #
* See the examples to understand better.
  https://dl.dropboxusercontent.com/u/116215806/Products/MoreAHK/talk_examples.7z
* If a script using this function is running as exe, use		script := new talk("ScriptName.exe")	and not just the Scriptname.
* Note that script names are case - sensitive.		For a script named "MyScript" , use   new talk("MyScript")  and not  new talk("myscript")
* setvar() will create the variable in the client script if it does not exist.
*/

/*
Class talk
	Methods
		setVar(var, value, wait:=true)	-	Sets the var in a client script. Optionally waits for the variable to be set
		getVar(var)	-	Gets the value of var in a client script
		runlabel(label, wait:=true)	-	runs a label in a client script. Optionally waits for the label to finish if wait = 1
		suspend(timeinms)	-	suspends a client script for timeinms
		terminate()	-	terminates or exits a client script
	Return Values
		Except getVar() which returns the value, all other function returns whether they were successful or not.
		Values
			Successful = 1
			Communication Request not accepted = 0
			(Client) Script not found = FAIL
*/




class talk
{
	__New(Client){
		if ( Substr(Client, -2) == "exe" )
			this.Script := Client
		else
			this.Script := ( Substr(Client, -2) == "ahk" ) ? Client : Client ".ahk"
		OnMessage(0x4a, "talk_reciever")
	}

	setVar(Var, value, wait:=true){
		StringReplace,value,value,\,\\,All
		T := talk_send(value " \ " A_ScriptName " \ " "setvar" " \ " Var (wait ? "*" : ""), this.Script)
		;uses * as a wait identifier
		if wait
		{
			while !talk.recieved
				sleep, 50
			talk.recieved := ""
		}
		return T
	}
	
	getVar(Var){
		global
		talk_send(var " \ " A_ScriptName " \ " "getvar", this.Script)

		while !talk.recieved
			sleep, 50
		talk.recieved := ""
		return talk.talk
	}

	runlabel(label, wait:=true){
		global
		StringReplace, label, label,\,\\,All
		T := talk_send(label " \ " A_scriptname " \ " "runlabel" " \ " wait, this.Script)
		if wait
		{
			while !talk.recieved
				sleep, 50
			talk.recieved := ""
		}
		return T
	}
	
	suspend(timeinms){
		return talk_send(timeinms " \ " A_scriptname " \ " "suspend", this.Script)
	}
	
	terminate(){
		return talk_send("terminate" " \ " A_scriptname " \ " "terminate", this.Script)
	}
}

talk_reciever(wParam, lParam){
	global
	local Data, Params, ScriptName, What, Param1, tosend, T
	
    Data := StrGet( NumGet(lParam + 2*A_PtrSize) )
	;Structure... Data \ SenderScriptName \ What \ Param1

	Params := Substr(Data, Instr(Data, " \ ")+3) , ScriptName := Substr(Params, 1, Instr(Params, " \ ")-1)
	What := Substr(Params, Instr(Params, " \ ")+3, Instr(Params, " \ ",false,1,2) - Instr(Params, " \ ") - 3)
	Param1 := Substr(Params, -(Strlen(Params) - Instr(Params, " \ ",false,0))+3)

	if what = 
		what := Param1		;incase of getvar
		
	Data := Substr(Data, 1, Instr(Data, " \ ")-1)

	if What = setvar
	{
		StringReplace,Data,Data,\\,\,All
		if Instr(Param1, "*")
			Param1 := Substr(Param1, 1, -1) , T := 1
		%Param1% := Data
		if T
			talk_send("setvar" " \ " A_ScriptName " \ " "talk", ScriptName)
		return
	}
	else if What = getvar
	{
		tosend := %Data%
		StringReplace,tosend,tosend,\,\\,All
		talk_send(tosend " \ " A_ScriptName " \ " "talk", ScriptName)
		return
	}
	else if What = talk
	{
		StringReplace,Data,Data,\\,\,All
		talk.recieved := 1 , talk.talk := Data
		return
	}
	else if What = runlabel
	{
		StringReplace, Data, Data,\\,\,All
		if islabel(Data)
			gosub, %Data%
		if Param1
			talk_send("runlabel" " \ " A_ScriptName " \ " "talk", ScriptName)
		return
	}
	else if What = suspend
	{
		Suspend
		sleep,% Data
		Suspend
		return
	}
	else if What = terminate
		ExitApp
}

talk_send(ByRef StringToSend, ByRef TargetScriptTitle){
    VarSetCapacity(CopyDataStruct, 3*A_PtrSize, 0)
	SizeInBytes := (StrLen(StringToSend) + 1) * (A_IsUnicode ? 2 : 1)
	NumPut(SizeInBytes, CopyDataStruct, A_PtrSize)
	NumPut(&StringToSend, CopyDataStruct, 2*A_PtrSize)
	Prev_DetectHiddenWindows := A_DetectHiddenWindows
	Prev_TitleMatchMode := A_TitleMatchMode
	DetectHiddenWindows On
	SetTitleMatchMode 2
    SendMessage, 0x4a, 0, &CopyDataStruct,, %TargetScriptTitle%
    DetectHiddenWindows %Prev_DetectHiddenWindows%
    SetTitleMatchMode %Prev_TitleMatchMode%
    return ErrorLevel
}

;__TalkRun_1.ahk

Code: Select all

#NoEnv 
#Persistent
#MaxMem
#include Talk().ahk
SendMode Input 
SetWorkingDir %A_ScriptDir%

new talk("")

loop 1000
{
var1 := "TalkRun_1.ahk <--> Var-" A_Index
sleep, 900
var2 := "Var-" A_Index
}

return
esc::exitapp
;zwei

Code: Select all

#NoEnv
#Persistent
#MaxMem
#include Talk().ahk
SendMode Input
SetWorkingDir %A_ScriptDir%

F10::
sleep, 500
Msgbox,,LoopTest, % xVarupdater(), 1
Return

return

xVarupdater(){
var1 := new talk("__TalkRun_1.ahk").getvar("var1")
var2 := new talk("__TalkRun_1.ahk").getvar("var2")
return var1 "`n" Var2
}

esc::exitapp
;drei

Code: Select all

#NoEnv
#Persistent
#MaxMem
#include Talk().ahk
SendMode Input
SetWorkingDir %A_ScriptDir%

sleep, 10

Loop
{
Msgbox,,LoopTest, % Varupdater(), 1
sleep, 500
}
Return

;--------------------------------------------------------------------------------------------------------;
Varupdater(){
var1 := new talk("__TalkRun_1.ahk").getvar("var1")
var2 := new talk("__TalkRun_1.ahk").getvar("var2")
return var1 "`n" Var2
}
;--------------------------------------------------------------------------------------------------------;

esc::exitapp

just me
Posts: 9451
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: talk() - Interscript communication auch bidirektional ?

Post by just me » 09 Jul 2020, 05:12

Moin effel,

erst einmal zur Terminologie:
'eins' empfängt Anfragen von 'zwei' und 'drei' und sendet denen ggf. den aktuellen Inhalt der abgefragten Variablen.

Das Ganze beruht auf der Nachricht WM_COPYDATA (0x004A). Damit können Daten zwischen verschiedenen Anwendungsfenstern ausgetauscht werden. Jede Anwendung kann dabei sowohl Sender als auch Empfänger sein. Wichtig ist nur, dass sich alle Beteiligten eindeutig identifizieren können.

talk von AVI packt das in eine Klasse und liefert damit Routinen für den Austausch vordefinierter Abfragen/Aktionen. Damit das funktioniert, müssen die Nachrichten einen vorgegebenen Aufbau haben. Ob das Deine Anforderungen erfüllt, weißt nur Du.

Wenn Du erläuterst, was genau Du austauschen willst, könnte man das auch auf die Grundfunktionen Nachricht senden und Nachricht empfangen reduzieren. Das wäre dann deutlich flexibler als die Klasse.

effel
Posts: 544
Joined: 16 Jan 2018, 13:34

Re: talk() - Interscript communication auch bidirektional ?

Post by effel » 09 Jul 2020, 06:00

hallo just me, ich habe für diese Scripte keine aktuelle Anwendung, bin nur beim stöbern auf `talk`gestoßen und weil es so interessant klang, habe ich damit etwas rum experimentiert.

Es gibt sicher viele Anwendungen, wo ich es brauchen könnte, wenn ich daten zwischen zwei scripten autauschen kann. Und das ohne eine TMP-Datei.

Beim basteln bekam ich es leider nur in eine Richtung hin, Daten zu versenden.

Es müsste es auch möglich sein bidirektional zu übertragen, so könnte ein script daten abarbeiten und seine Bereitschaft für den nächsten Datensatz mit einem True zu signalisieren. Ein Integrierter Schaltkreis machte mir diese Denkweise vor.

Die Infos von der Ursprungs-Webseite reichen mir leider nicht aus, das ganze zu verstehen, so bin ich darauf angewiesen rumzubasteln :-) oder euch hier mit meinem unqualifizierten Fragen zu nerven.

Es ist nur Learning By Doing für mich. Ohne Ziel...

just me
Posts: 9451
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: talk() - Interscript communication auch bidirektional ?

Post by just me » 09 Jul 2020, 07:51

Hallo effel,

ich werde demnächst mal ein Beispiel einstellen, vielleicht aber in Tutorials.

Post Reply

Return to “Ich brauche Hilfe”