Jump to content

ScriptControl Vbscript 2way communication


Recommended Posts

Using ScriptControl method.... test two way communication between Autoit and Vbscript.
So I started this thread ( DllStructCreate & DllStructGetPtr ) to find a solution to communication between two Autoit script.

@LarsJ already posted two nice example how it possible using ROT objects.

So this example using ScriptControl not that important but still posting :D

#include <string.au3>
#include <Array.au3>

Global $oError = ObjEvent("AutoIt.Error", "_ErrFunc")
Func _ErrFunc()
    ConsoleWrite("! COM Error !  Number: 0x" & Hex($oError.number, 8) & "   ScriptLine: " & $oError.scriptline & " - " & $oError.windescription & @CRLF)
    Return
EndFunc   ;==>_ErrFunc

__Example1()
Func __Example1()
    Local $o_JsCode = __ReadCodeBlock("#cs;CodeBlock", "#ce;CodeBlock")

    Local $o_FakeObj
    Local $tFakeObj
    $o_FakeObj = __ObjectFromTag("__MyInterface_", "Message hresult(bstr)", $tFakeObj)
    $o_FakeObj.Message("Test from Autoit")

    Local $TestMsg = "Message from"
    Global $o_Obj = 0
    $o_Obj = ObjCreate("ScriptControl")
    $o_Obj.Language = "vbscript"
    $o_Obj.AddObject("AutoitObj", $o_FakeObj)
    $o_Obj.AddCode($o_JsCode)
    $o_Obj.run('Test', $TestMsg)

    $o_Obj = 0
    If IsObj($o_FakeObj) Then $o_FakeObj = 0
    MsgBox(0, '', "The End.")
EndFunc

Func __MyInterface_QueryInterface($pSelf, $pRIID, $pObj)
    Local $tStruct = DllStructCreate("ptr", $pObj)
    DllStructSetData($tStruct, 1, $pSelf)
    Return 0 ; $S_OK
EndFunc

Func __MyInterface_AddRef($pSelf)
    Return 1
EndFunc

Func __MyInterface_Release($pSelf)
    Return 1
EndFunc

Func __MyInterface_Message($pSelf, $pString)
    Local $o_Data = DllStructGetData(DllStructCreate("wchar[" & _
                    DllStructGetData(DllStructCreate("dword", $pString - 4), 1) / 2 & "]", $pString), 1)

    If StringInStr($o_Data, "|") Then
        Local $aArray = StringSplit($o_Data, '|', 2)
        $o_Data = $aArray[1]
        Call($aArray[0], $aArray[1])
    Endif

    MsgBox(0, 'FakeObj', $o_Data)
    Return 0 ; $S_OK
EndFunc

Func __MessageEdit($oMsg)
    Local $aPos = MouseGetPos()
    Local $aMsg = "Mouse x, y: " & $aPos[0] & ", " & $aPos[1]
    $o_Obj.run('SetMessage', $oMsg & " <> [" & $aMsg & "]")
EndFunc

; #FUNCTION# =============================================================================
; Name...........: __ReadCodeBlock
; ========================================================================================
Func __ReadCodeBlock($o_Start, $o_End)
    Local $sStart = @LF & $o_Start
    Local $sEnd = $o_End & @CR
    Local $aArray = _StringBetween(FileRead(@ScriptFullPath), $sStart, $sEnd)
    Return $aArray[0]
EndFunc

; #FUNCTION# =============================================================================
; Name...........: __ObjectFromTag
; ========================================================================================
Func __ObjectFromTag($sFunctionPrefix, $tagInterface, ByRef $tInterface, $fPrint = False, $bIsUnknown = Default, $sIID = "{00000000-0000-0000-C000-000000000046}") ; last param is IID_IUnknown by default
    If $bIsUnknown = Default Then $bIsUnknown = True
    Local $sInterface = $tagInterface ; copy interface description
    Local $tagIUnknown = "QueryInterface hresult(ptr;ptr*);" & _
            "AddRef dword();" & _
            "Release dword();"
    ; Adding IUnknown methods
    If $bIsUnknown Then $tagInterface = $tagIUnknown & $tagInterface
    ; Below line is really simple even though it looks super complex. It's just written weird to fit in one line, not to steal your attention
    Local $aMethods = StringSplit(StringReplace(StringReplace(StringReplace(StringReplace(StringTrimRight(StringReplace(StringRegExpReplace(StringRegExpReplace($tagInterface, "\w+\*", "ptr"), "\h*(\w+)\h*(\w+\*?)\h*(\((.*?)\))\h*(;|;*\z)", "$1\|$2;$4" & @LF), ";" & @LF, @LF), 1), "object", "idispatch"), "hresult", "long"), "bstr", "ptr"), "variant", "ptr"), @LF, 3)
    Local $iUbound = UBound($aMethods)
    Local $sMethod, $aSplit, $sNamePart, $aTagPart, $sTagPart, $sRet, $sParams, $hCallback
    ; Allocation
    $tInterface = DllStructCreate("int RefCount;int Size;ptr Object;ptr Methods[" & $iUbound & "];int_ptr Callbacks[" & $iUbound & "];ulong_ptr Slots[16]") ; 16 pointer sized elements more to create space for possible private props
    If @error Then Return SetError(1, 0, 0)
    For $i = 0 To $iUbound - 1
        $aSplit = StringSplit($aMethods[$i], "|", 2)
        If UBound($aSplit) <> 2 Then ReDim $aSplit[2]
        $sNamePart = $aSplit[0]
        $sTagPart = $aSplit[1]
        $sMethod = $sFunctionPrefix & $sNamePart
        If $fPrint Then
            Local $iPar = StringInStr($sTagPart, ";", 2), $t
            If $iPar Then
                $t = "Ret: " & StringLeft($sTagPart, $iPar - 1) & "  " & _
                        "Par: " & StringRight($sTagPart, StringLen($sTagPart) - $iPar)
            Else
                $t = "Ret: " & $sTagPart
            EndIf
            Local $s = "Func " & $sMethod & _
                    "( $pSelf ) ; " & $t & @CRLF & _
                    "EndFunc" & @CRLF
            ConsoleWrite($s)
        EndIf
        $aTagPart = StringSplit($sTagPart, ";", 2)
        $sRet = $aTagPart[0]
        $sParams = StringReplace($sTagPart, $sRet, "", 1)
        $sParams = "ptr" & $sParams
        $hCallback = DllCallbackRegister($sMethod, $sRet, $sParams)
        If @error Then
            ConsoleWrite('! ' & @error & ' ' & $sMethod & @CRLF & @CRLF)
        EndIf

        DllStructSetData($tInterface, "Methods", DllCallbackGetPtr($hCallback), $i + 1) ; save callback pointer
        DllStructSetData($tInterface, "Callbacks", $hCallback, $i + 1) ; save callback handle
    Next
    DllStructSetData($tInterface, "RefCount", 1) ; initial ref count is 1
    DllStructSetData($tInterface, "Size", $iUbound) ; number of interface methods
    DllStructSetData($tInterface, "Object", DllStructGetPtr($tInterface, "Methods")) ; Interface method pointers
    Return ObjCreateInterface(DllStructGetPtr($tInterface, "Object"), $sIID, $sInterface, $bIsUnknown) ; pointer that's wrapped into object
EndFunc   ;==>ObjectFromTag

#cs;CodeBlock
Dim oString
oString = ""

Sub SetMessage(oMessage)
    oString = oMessage
End Sub

Function GetMessage()
    GetMessage = oString
End Function

Sub Test(oMessage)
    Dim AutoitFunc
    MsgBox("Test Start....")
    AutoitObj.Message("__MessageEdit|" & oMessage & " Autoit to Vbscript")
    AutoitFunc = GetMessage
    AutoitObj.Message(AutoitFunc)
End Sub
#ce;CodeBlock
;

 

Edited by jugador
Link to post
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
  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...