RemoteInvocation - call functions and set variables between scripts

Post your working scripts, libraries and tools
User avatar
Capn Odin
Posts: 1308
Joined: 23 Feb 2016, 19:45
Location: Denmark

RemoteInvocation - call functions and set variables between scripts

04 Sep 2018, 17:32

Introduction[hr][/hr]
I believe this already exists as I thought I would try making it after hearing of a similar library.
The script can call functions and set global variable in other scripts that also includes RemoteInvocation.
Limitations: only strings are supported as arguments. Additionally a script that includes this will be persistent.


Source

Code: Select all

InvokeVariable(title, variable, value) {
	text := variable "=" value
	RemotePost(0x1fe0, text, title)
}

InvokeFunction(title, function, parameters*) {
	text := function "("
	if(parameters.Length()) {
		for i, parameter in parameters {
			text .= StrReplace(parameter, ",", "#¤#") ","
		}
		text := SubStr(text, 1, -1)
	}
	text .= ")"
	RemotePost(0x1fe1, text, title)
}

RemoteInvocationVariable(pID, lParam, msg, hwnd) {
	Critical
	Static __ := OnMessage(0x1fe0, "RemoteInvocationVariable")
	expression := ReadPointer(pID, lParam)
	if(InStr(expression, "=")) {
		args := StrSplit(expression, "=", 2)
		if(args[1] != "") {
			var := RegExReplace(args[1], "\s", "")
			%var% := args[2]
		} else {
			RemotePostError("Can't set a variable without a name", "ahk_pid " pID)
		}
	} else {
		RemotePostError("Malformed argument, lacking an equal sign", "ahk_pid " pID)
	}
}

RemoteInvocationFunction(pID, lParam, msg, hwnd) {
	Critical
	Static __ := OnMessage(0x1fe1, "RemoteInvocationFunction")
	expression := ReadPointer(pID, lParam)
	args := StrSplit(expression, "(", 2)
	if(IsFunc(args[1])) {
		fun := Func(args[1])
		arguments := __RestoreCommas(StrSplit(SubStr(args[2], 1, -1), ","))
		if(fun.MinParams <= arguments.Length() && (fun.IsVariadic || fun.MaxParams >= arguments.Length())) {
			fun.Call(arguments*)
		} else {
			RemotePostError(__FunctionErrorMessage(fun, arguments), "ahk_pid " pID)
		}
	} else {
		RemotePostError("Function """ args[1] """ does not exist", "ahk_pid " pID)
	}
}

__RestoreCommas(arguments) {
	loop % arguments.Length() {
		arguments[A_Index] := StrReplace(arguments[A_Index], "#¤#", ",")
	}
	return arguments
}

__FunctionErrorMessage(fun, arguments) {
	return (arguments.Length() < fun.MinParams ? "Only " : "") arguments.Length() " argument(s) passed to function """ fun.Name """, which expects " fun.MinParams " arguments" (fun.MaxParams - fun.MinParams ? " with additional " fun.MaxParams - fun.MinParams " (optional) argument(s)." : ".")
}

RemoteInvocationError(pID, lParam, msg, hwnd) {
	Critical
	Static __ := OnMessage(0x1fe2, "RemoteInvocationError")
	msg := ReadPointer(pID, lParam)
	DetectHiddenWindows, On
	WinGetTitle, title, % "ahk_pid " pID
	RegExMatch(title, "\\\K[^\\]+.ahk", file)
	MsgBox, 0x30, % "Remote Invocation Error - " A_ScriptName, % "Error: " msg "`nin """ (file ? file : title) """"
}

ReadPointer(pID, lpBaseAddress){
	Static PROCESS_ALL_ACCESS := 0x1F0FFF, nSize := 50
	hProcess := DllCall("OpenProcess", "UInt", PROCESS_ALL_ACCESS, "UInt", True, "UInt", pID)
	
	VarSetCapacity(lpBuffer, nSize)
	VarSetCapacity(lpNumberOfBytesRead, 8)
	
	DllCall("ReadProcessMemory", "UPtr", hProcess, "UPtr", lpBaseAddress, "UPtr", &lpBuffer, "UInt", nSize, "UPtr", &lpNumberOfBytesRead)
	msgobj := StrSplit(StrGet(&lpBuffer, "UTF-16"), "#")
	
	VarSetCapacity(lpBuffer, msgobj[1]+0, 0)
	DllCall("ReadProcessMemory", "UPtr", hProcess, "UPtr", msgobj[2]+0, "UPtr", &lpBuffer, "UInt", msgobj[1]+0, "UPtr", &lpNumberOfBytesRead)
	Return StrGet(&lpBuffer, "UTF-16")
}

RemotePostError(text, title) {
	RemotePost(0x1fe2, text, title)
}

RemotePost(msgNum, text, title) {
	Static mem := "", mem2 := ""
	mem2 := text
	mem := VarSetCapacity(mem2, -1) "#" &mem2
	PostMessage, % msgNum, % GetPID(), % &mem, , % title
}

GetPID() {
	Process, Exist
	return ErrorLevel
}
Example

Run Function.ahk before Example.ahk.

Code: Select all

#Include RemoteInvocation.ahk

DetectHiddenWindows, On
SetTitleMatchMode, 2

Sleep, 1000

lorem_ipsum =
(
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean fermentum risus id tortor. Integer pellentesque quam vel velit. Praesent id justo in neque elementum ultrices. Nunc tincidunt ante vitae massa. Etiam sapien elit, consequat eget, tristique non, venenatis quis, ante. Duis ante orci, molestie vitae vehicula venenatis, tincidunt ac pede. Maecenas lorem. Nam sed tellus id magna elementum tincidunt. Integer pellentesque quam vel velit. Nullam dapibus fermentum ipsum. Phasellus rhoncus. Etiam dui sem, fermentum vitae, sagittis id, malesuada in, quam. 
)

loop 30 {
	str .= lorem_ipsum
}

InvokeFunction("Function.ahk", "fun", str)

Code: Select all

#Include RemoteInvocation.ahk

fun(a) {
	MsgBox, % a
	StrReplace(a, "Lorem ipsum", , Count)
	MsgBox, % Count
}
Please excuse my spelling I am dyslexic.

Return to “Scripts and Functions”

Who is online

Users browsing this forum: dobbelina and 17 guests