Page 1 of 1

Can I Call A Label From A Different AHK Script?

Posted: 20 Jan 2022, 14:16
by Mulsiphix
My goal is to allow ScriptA to execute a Label from ScriptB, without having to duplicate the Label code from ScriptB inside ScriptA. I'm trying to keep what I am working on as clean as possible. Just not sure if what I want here is possible. Ideally, it would work like this:

1. Start ScriptA
2. In the auto-execute section of Script A is some sort of command to auto-load ScriptB. ScriptB utilizes a hotkey, so it's loading doesn't produce any immediate effects.
3. Within ScriptA I specify "Gosub, ScriptB_label" and ScriptA is able to run said label from ScriptB. When the label is finished, the script returns to executing ScriptA code, just like you would normally expect with labels and the Gosub command.

Note: I tried utilizing #Include, but afterwards the hotkey in ScriptA no longer functions. #Include effectively breaks ScriptA. I found this information on the #Include page: "A script behaves as though the included file's contents are physically present at the exact position of the #Include directive (as though a copy-and-paste were done from the included file). Consequently, it generally cannot merge two isolated scripts together into one functioning script.".

So maybe #Include isn't the command I am looking for :roll: . Any other possibilities?

Re: Can I Call A Label From A Different AHK Script?

Posted: 20 Jan 2022, 15:09
by amateur+
ScriptA:

Code: Select all

#Include ScriptB.ahk
gosub myLabel
return

F4::MsgBox, F4
ScriptB:

Code: Select all

myLabel:
MsgBox, aaa
return

F3::MsgBox, F3
Everything works.

Re: Can I Call A Label From A Different AHK Script?

Posted: 20 Jan 2022, 15:16
by gregster
amateur+ wrote:
20 Jan 2022, 15:09
ScriptA:

Code: Select all

#Include ScriptB.ahk
gosub myLabel
return

F4::MsgBox, F4
ScriptB:

Code: Select all

myLabel:
MsgBox, aaa
return

F3::MsgBox, F3
Everything works.
If you include this ScriptB at the beginning of this ScriptA, you will run into a problem. gosub myLabel will be unreachable and won't get executed. There are two returns above it - one is explicit (end of the labeled subroutine), one implicit (of the one-liner hotkey F3).

Of course, in this simple case, the flow of execution will run into the labeled subroutine anyway, because it is now at the top of the auto-execution section (while the gosub is still unreachable), but this example is still misleading.

Re: Can I Call A Label From A Different AHK Script?  Topic is solved

Posted: 20 Jan 2022, 15:24
by amateur+
@gregster, you're right, it was a mistake. What about this one?
ScriptA:

Code: Select all

gosub F3
return

F4::MsgBox, F4

#Include ScriptB.ahk
ScriptB:

Code: Select all

F3::MsgBox, F3

Re: Can I Call A Label From A Different AHK Script?

Posted: 20 Jan 2022, 15:27
by gregster
Yes, this will work (jumps to normal labels should also work).
It is important to remember that including is like copy&pasting the to be included code into the including script, at the exact spot where the #include directive is located.

Re: Can I Call A Label From A Different AHK Script?

Posted: 20 Jan 2022, 17:29
by boiler
If you just want to call something from another running script, you can use ObjRegisterActive() for one script to call a method (function in a class) from another script. For example:

Run this script:

Code: Select all

#Persistent
ObjRegisterActive(MyObject, "{8B3BC8D2-01FB-4C5B-BCCC-909D81C76A3E}")
return

class MyObject {
    DisplayMessage(Message) {
        MsgBox, % Message
    }
}

/*
    ObjRegisterActive(Object, CLSID, Flags:=0)
    
        Registers an object as the active object for a given class ID.
        Requires AutoHotkey v1.1.17+; may crash earlier versions.
    
    Object:
            Any AutoHotkey object.
    CLSID:
            A GUID or ProgID of your own making.
            Pass an empty string to revoke (unregister) the object.
    Flags:
            One of the following values:
              0 (ACTIVEOBJECT_STRONG)
              1 (ACTIVEOBJECT_WEAK)
            Defaults to 0.
    
    Related:
        http://goo.gl/KJS4Dp - RegisterActiveObject
        http://goo.gl/no6XAS - ProgID
        http://goo.gl/obfmDc - CreateGUID()
*/
ObjRegisterActive(Object, CLSID, Flags:=0) {
    static cookieJar := {}
    if (!CLSID) {
        if (cookie := cookieJar.Remove(Object)) != ""
            DllCall("oleaut32\RevokeActiveObject", "uint", cookie, "ptr", 0)
        return
    }
    if cookieJar[Object]
        throw Exception("Object is already registered", -1)
    VarSetCapacity(_clsid, 16, 0)
    if (hr := DllCall("ole32\CLSIDFromString", "wstr", CLSID, "ptr", &_clsid)) < 0
        throw Exception("Invalid CLSID", -1, CLSID)
    hr := DllCall("oleaut32\RegisterActiveObject"
        , "ptr", &Object, "ptr", &_clsid, "uint", Flags, "uint*", cookie
        , "uint")
    if hr < 0
        throw Exception(format("Error 0x{:x}", hr), -1)
    cookieJar[Object] := cookie
}

Then run this separate script that passes a parameter to the method in the other script for it to act upon:

Code: Select all

#Persistent
x := ComObjActive("{8B3BC8D2-01FB-4C5B-BCCC-909D81C76A3E}")
x.DisplayMessage("Hello, world!")

Re: Can I Call A Label From A Different AHK Script?

Posted: 20 Jan 2022, 19:35
by Mulsiphix
Thank you amateur+ for this script. Thank you gregster for helping make it all it can be. My script is working as desired now. Thank you! :thumbup:

boiler, your script is a little harder for me to understand. I plan on playing with it later tonight and seeing if I can get it integrated with my script. Thank you very much for sharing this with me. I really appreciate the remarks inside to help me understand how to use it. This is awesome. Thank you as well! :dance:

Re: Can I Call A Label From A Different AHK Script?

Posted: 20 Jan 2022, 19:41
by boiler
Mulsiphix wrote: I really appreciate the remarks inside to help me understand how to use it.
The function and all the remarks in it are courtesy of lexikos. I just shortened up one of his examples to make it a little easier to follow.