Jump to content

Hooks in AutoIt


jvanegmond
 Share

Recommended Posts

Just some random idea I had in my head for a while. The ability to add multiple hooks to call multiple functions with multiple arguments. Basically an extension on "Call", but could be simplified so much that it would become useful in many different situations.

I don't see any practical uses for this yet until we can dynamically include files. (IE Compile on run-time) But I thought I'd post it anyway, because someone might get inspired with the idea.

; ######### Hook Library #########
; Library of hooks. #include "Hooks.au3"

Local $Hooks[1][3]

Func hookAdd($Hook, $Hookname, $Funcname)
    Local $i = UBound($Hooks,1)+1
    ReDim $Hooks[$i][3]
    $Hooks[$i-1][0] = $Hook
    $Hooks[$i-1][1] = $Hookname
    $Hooks[$i-1][2] = $Funcname
EndFunc

Func hookRemove($Hook, $Hookname)
    For $i = 0 to UBound($Hooks,1)-1
        If $Hooks[$i][0] = $Hook AND $Hooks[$i][1] = $Hookname Then
            $Hooks[$i][0] = ""
            $Hooks[$i][1] = ""
            $Hooks[$i][2] = ""
        EndIf
    Next
EndFunc

Func hookCall($Hook, $Param1 = Default, $Param2 = Default, $Param3 = Default, $Param4 = Default, $Param5 = Default);etc;etc;etc
    Local $iFoundHook = 0, $sExecuteStringParams
    For $i = 0 to UBound($Hooks,1)-1
        if $Hooks[$i][0] = $Hook Then
         ;; There's probably a lot better way to do this xD, yes :)
            $iFoundHook += 1
            Dim $avCallArgArray[6] = [ 'CallArgArray', $Param1, $Param2, $Param3, $Param4, $Param5]
            ReDim $avCallArgArray[@NumParams]
            Call ( $Hooks[$i][2], $avCallArgArray )
        EndIf
    Next
    
    Return $iFoundHook
EndFunc


;######### Plugin / Addon ##########
; This should be dynamically included for high win-factor, but this is impossible in AutoIt.

; Shows a simple hook
Func MyThink()
    ConsoleWrite("Think hook was called" & @CRLF)
EndFunc
hookAdd("Think", "mythinkhook", "MyThink")

; Shows that hooks can be called twice
Func MyInitialize($StartTime)
    ConsoleWrite("We started at: " & $StartTime & @CRLF)
EndFunc
hookAdd("Initialize", "myinitializehook", "MyInitialize")

Func MyInitializeAgain($StartTime)
    ConsoleWrite("No seriously, we really started at: " & $StartTime & @CRLF)
EndFunc
hookAdd("Initialize", "myinitializehook", "MyInitializeAgain")

; A sample hook with one input
Func MyEvenNumberHook($Number)
    ConsoleWrite("This is an even number: " & $Number & @CRLF)
EndFunc
hookAdd("EvenNumber", "myeventnumber", "MyEvenNumberHook")

; Shows hooks can be removed and can be called twice
Func MyHookThatIsNeverCalled()
    ConsoleWrite("If you see this, you did something wrong." & @CRLF)
EndFunc
hookAdd("Think","hookthatisnevercalled","MyHookThatIsNeverCalled")
hookRemove("Think","hookthatisnevercalled")


;########## Engine / Original program #############
; The following lines of code never change depending on the plugins / addons

Dim $n = 0

hookCall("Initialize", TimerInit() )

While 1
    hookCall("Think")
    $n += 1
    If Mod($n,2) = 0 Then
        hookCall("EvenNumber", $n)
    Else
        hookCall("UnevenNumber", $n)
    EndIf
    
    Sleep(300)
WEnd

I know the array isn't very neat yet and that it gets a real mess if you remove a lot of hooks.

Idea came from: http://code.garrysmod.com/?show=/garrysmod...odules/hook.lua

Edited by Manadar
Link to comment
Share on other sites

Some sample output:

We started at: 37136709661
No seriously, we really started at: 37136709661
Think hook was called
Think hook was called
This is an even number: 2
Think hook was called
Think hook was called
This is an even number: 4
Think hook was called
Think hook was called
This is an even number: 6
Link to comment
Share on other sites

you could just do

If Not $Param1 Then
                Call($Hooks[$i][2])
            ElseIf Not $Param2 Then
                Call($Hooks[$i][2], $Param1)
            ElseIf Not $Param3 Then
                Call($Hooks[$i][2], $Param1, $Param2)
            ElseIf Not $Param3 Then
                Call($Hooks[$i][2], $Param1, $Param2, $Param3)
            EndIf

if param1 isent false the it has to be true.

[font="Impact"]Never fear, I is here.[/font]

Link to comment
Share on other sites

Yes, that makes more sense. I must have been working with assembly a bit too much recently.

To deal with any number of parameters you could do something like this

Local Dim $RealPars[$MAX_NUM_PARAMS]
Local $LastPar = $MAX_NUM_PARAMS;must be defined somewhere
For $n = 1 To $MAX_NUM_PARAMS
    RealPars[$n] = Eval("Par" & $n)
    If @error Then
        $LastPar = $n - 1
        ExitLoop
    EndIf
Next

Local $Arrayset[$LastPar]

$Arrayset[0] = "CallArgArray"

For $n = 1 To $LastPar
    $Arrayset[$n] = Eval($RealPars[$n])
Next

Call($Hooks[$i][2], $Arrayset)

Which is taken from the idea I use in my OnEvent udf.

No allowance has been made for functions which use ByRef.

Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.
Link to comment
Share on other sites

Hey martin, I thought about doing that. But I'd rather not return an array. Trying to keep it simple. I know your way is the only way that will work eventually, so thanks for that.

Why do you have "ElseIf Not $Param3 Then" two times?? >_< That doesn't make any sense at all to me :)

Comment on the concept, not every little mistake in the code. >_> Edited by Manadar
Link to comment
Share on other sites

Hey martin, I thought about doing that. But I'd rather not return an array. Trying to keep it simple. I know your way is the only way that will work eventually, so thanks for that.

Comment on the concept, not every little mistake in the code. >_>

Where are you returning an array?
Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.
Link to comment
Share on other sites

Comment on the concept, not every little mistake in the code. >_>

The concept is good, but I don't see myself using it anytime soon, mainly because "dynamic includes" doesn't seem to be on the roadmap >_<

This would actually fit perfectly in "Franks Gadget" because having to restart everytime you add or remove a gadget is a big pain in the ass when testing everything during development :)

Link to comment
Share on other sites

I meant this part. I'd rather not give an array with arguments to what the hook calls.

For $n = 1 To $LastPar
    $Arrayset[$n] = Eval($RealPars[$n])
Next

Call($Hooks[$i][2], $Arrayset)
Ok, but I don't see the problem. The array I built has the first element as "CallArgArray" so it is equivalent to what you already had. It doesn't mean you are passing an array to the functions because Call detects that the first element is "CallArgArray" and then sends the remaining elements as individual parameters.
Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.
Link to comment
Share on other sites

My Hookcall, updated again.

Func hookCall($Hook, $Param1 = Default, $Param2 = Default, $Param3 = Default, $Param4 = Default, $Param5 = Default);etc;etc;etc
    Local $iFoundHook = 0, $sExecuteStringParams
    For $i = 0 to UBound($Hooks,1)-1
        if $Hooks[$i][0] = $Hook Then
         ;; There's probably a lot better way to do this xD, yes :)
            $iFoundHook += 1
            Dim $avCallArgArray[6] = [ 'CallArgArray', $Param1, $Param2, $Param3, $Param4, $Param5]
            ReDim $avCallArgArray[@NumParams]
            Call ( $Hooks[$i][2], $avCallArgArray )
        EndIf
    Next
    
    Return $iFoundHook
EndFunc

A question, why are you using $Hookname is think its useless, we could make $hookname and $functioname the same.

Edited by 4nt1h4cker
Link to comment
Share on other sites

Ok, but I don't see the problem. The array I built has the first element as "CallArgArray" so it is equivalent to what you already had. It doesn't mean you are passing an array to the functions because Call detects that the first element is "CallArgArray" and then sends the remaining elements as individual parameters.

Ohh, now I remember that functionality. It makes sense now, thanks for that piece of code.

This is typical in AutoIt. "Let us do it the way no other language does this, lets forget the defined paths and we'll just do what we want to do." Lua and C#, for example, have great functionality for these kind of things.

from your code:What about Execute() ? :)

ASFARBLARGH! GET AWAY!

A question, why are you using $Hookname is think its useless, we could make $hookname and $functioname the same.

You're right. It is useless. I was going to make Hookname hold the function itself, but now I realise the function is just a string, because there is no function datatype it becomes redundant. I'll work it out in the next version. Thanks for teh code. Edited by Manadar
Link to comment
Share on other sites

everything written with Execute can be written without Execute.

I wont agree with that.

$iDimensions = UBound($aArray,0)
$sDimensions = ""

for $i = 1 to $iDimensions
    $sDimensions &= "[0]"
Next

$iValue = Execute("$aArray"&$sDimensions)

How are you gonna do that without execute?

Edited by Kip
Link to comment
Share on other sites

  • 2 weeks later...

You're right, you simply can not do that. It's a language restriction, and can be done in many other languages like so:

Dim $aArray[3][2] = [ [ 1, 2 ] , _
[ 3, 4 ], _
[ 5, 6 ] ]

$tVal = $aArray

While 1
    If IsArray($tVal) == 1 Then
        $tVal = $tVal[0] ; Would return an array
    Else
        ExitLoop
    EndIf
WEnd

ConsoleWrite($tVal & @CRLF)
Edited by Manadar
Link to comment
Share on other sites

  • 3 weeks later...

Having one adlib call multiple functions, can be expanded to create timers in pure AutoIt.

; ######### Hook Library #########
; Library of hooks. #include "Hooks.au3"

Local $Hooks[1][3]

Func hookAdd($Hook, $Hookname, $Funcname)
    Local $i = UBound($Hooks,1)+1
    ReDim $Hooks[$i][3]
    $Hooks[$i-1][0] = $Hook
    $Hooks[$i-1][1] = $Hookname
    $Hooks[$i-1][2] = $Funcname
EndFunc

Func hookRemove($Hook, $Hookname)
    For $i = 0 to UBound($Hooks,1)-1
        If $Hooks[$i][0] = $Hook AND $Hooks[$i][1] = $Hookname Then
            $Hooks[$i][0] = ""
            $Hooks[$i][1] = ""
            $Hooks[$i][2] = ""
        EndIf
    Next
EndFunc

Func hookCall($Hook, $Param1 = Default, $Param2 = Default, $Param3 = Default, $Param4 = Default, $Param5 = Default);etc;etc;etc
    Local $iFoundHook = 0, $sExecuteStringParams
    For $i = 0 to UBound($Hooks,1)-1
        if $Hooks[$i][0] = $Hook Then
         ;; There's probably a lot better way to do this xD, yes 
            $iFoundHook += 1
            Dim $avCallArgArray[6] = [ 'CallArgArray', $Param1, $Param2, $Param3, $Param4, $Param5]
            ReDim $avCallArgArray[@NumParams]
            Call ( $Hooks[$i][2], $avCallArgArray )
        EndIf
    Next
    
    Return $iFoundHook
EndFunc


;######### Plugin / Addon ##########
; This should be dynamically included for high win-factor, but this is impossible in AutoIt.

; Shows a simple hook
Func MyThink()
    ConsoleWrite("Think hook was called" & @CRLF)
EndFunc
hookAdd("Adlib", "mythinkhook", "MyThink")
Func MyThink2()
    ConsoleWrite("Think2 hook was called" & @CRLF)
EndFunc
hookAdd("Adlib", "mythinkhook", "MyThink2")
Func MyThink3()
    ConsoleWrite("Think3 hook was called" & @CRLF)
EndFunc
hookAdd("Adlib", "mythinkhook", "MyThink3")

;########## Engine / Original program #############
; The following lines of code never change depending on the plugins / addons

AdlibEnable("SomeAdlibFunc", 1000)

While 1
    
WEnd

Func SomeAdlibFunc()
    hookCall("Adlib")
EndFunc
Link to comment
Share on other sites

If your goal is to dynamically include crap why not do it yourself? Like parse it your self using an execute or similer function for functions and then if statements for keywords such as loops etc. ? Than load the sequence to memory, and recall as needed. It makes sense to me ok.

[center][/center]Working on the next big thing.Currently Playing: Halo 4, League of LegendsXBL GT: iRememberYhslaw

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...