Jump to content

Convert GetRef function from VBScript to AutoIt


Recommended Posts

impossible to convert GetRef function from VBScript to AutoIt.

Edited by Melba23
Reset title as thread is now alive again

Sorry if it's quite challenging to understand me sometimes, there is 2 possible reasons to this:

Spoiler

#1. I am a native French speaker and learned English mainly from chatting with others players in online games.

#2. I have a developmental disorder mainly affecting my social abilities, way of thinking, understanding stuffs and explaining myself in which it can seem ironic of seeing me here, but I been working on getting better every days for an dozens of years now ^_^

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Do not like my dirty code? It's fine, but in my opinion, the dirty codes are unique and I believe it's a good glimpse of how the mind of the person who wrote it thinks, and that, that's what I call a psychological deduction step by step in all its splendor.

~WilliamasKumeliukas

Link to post
Share on other sites
On 9/17/2021 at 5:47 PM, JockoDundee said:

why not:

Func GetRef($sFunc)

   Return Execute($sFunc)

EndFunc

 

It return as Unknown Type and triggers COM Error handler when It expect to return as Object Type when I use your function :(

If you didn't read my first post before I removed the contents within it, I can repost it again

 

Regards,

~WilliamasKumeliukas

Edited by WilliamasKumeliukas

Sorry if it's quite challenging to understand me sometimes, there is 2 possible reasons to this:

Spoiler

#1. I am a native French speaker and learned English mainly from chatting with others players in online games.

#2. I have a developmental disorder mainly affecting my social abilities, way of thinking, understanding stuffs and explaining myself in which it can seem ironic of seeing me here, but I been working on getting better every days for an dozens of years now ^_^

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Do not like my dirty code? It's fine, but in my opinion, the dirty codes are unique and I believe it's a good glimpse of how the mind of the person who wrote it thinks, and that, that's what I call a psychological deduction step by step in all its splendor.

~WilliamasKumeliukas

Link to post
Share on other sites

first off, you need to understand what GetRef actually does

https://www.vbsedit.com/html/f9643b79-b4a1-4f70-9017-2b2e2f01ef3a.asp#:~:text=The GetRef function allows you,available for its various objects.

 

then you need to code to those requirements.

 

read this

https://www.oreilly.com/library/view/vbscript-in-a/0596004885/re109.html

 

if you are comparing to VBA, that isn't supported in VBA, only VBScript

 

so, do you have an DHTML page you wish do do things with/on? why are you deleting your posts?

 

 

Edited by Earthshine

My resources are limited. You must ask the right questions

 

Link to post
Share on other sites
1 hour ago, Earthshine said:

first off, you need to understand what GetRef actually does

https://www.vbsedit.com/html/f9643b79-b4a1-4f70-9017-2b2e2f01ef3a.asp#:~:text=The GetRef function allows you,available for its various objects.

 

then you need to code to those requirements.

 

read this

https://www.oreilly.com/library/view/vbscript-in-a/0596004885/re109.html

 

if you are comparing to VBA, that isn't supported in VBA, only VBScript

 

so, do you have an DHTML page you wish do do things with/on? why are you deleting your posts?

 

 

This script download Windows Updates asynchronously and track progress  You can also explore methods / properties / etc from a object browser by loading this dll (C:\Windows\SysWOW64\wuAPI.dll) 

I know how to do it in VBScript, but I don't know what I am missing or doing wrong in AutoIt 😕 GetRef is used to accomplish this: link

(Note: I can provide both full scripts if the following snippets arent helping much)

In VBScript, It is used like this:

 

Function Download(Byval hCollection)
    Dim Result

    Set Downloader = updateSession.CreateUpdateDownloader()
    Downloader.Updates = hCollection

    Set DownloadJob = Downloader.BeginDownload(GetRef("Download_OnProgressChanged"), GetRef("Download_OnCompleted"), "")
    If Not Err.Number = 0 Then
        WScript.StdOut.WriteLine "Error " & Err.Number & ": " & Err.Description
    End If
 
    Do Until DownloadJob.IsCompleted
        WScript.Sleep 1000
    Loop

    Set Download = Downloader.EndDownload(DownloadJob)
End Function




Sub Download_OnProgressChanged(ByVal hDownloadJob, ByVal hArguments)
    WScript.StdOut.WriteLine "Activity=""Processing Windows Updates on " & strComputerName & """ Status=""Downloading updates"" Percentage=" & hArguments.Progress.PercentComplete
End Sub




Sub Download_OnCompleted(ByVal hInstallJob, ByVal hArguments)
    WScript.StdOut.WriteLine "Activity=""Processing Windows Updates on " & strComputerName & """ Status=""Downloading updates"" Percentage=100"
End Sub

in AutoIt I try reproducing the same like this:

Global $oMyError = ObjEvent("AutoIt.Error","MyErrFunc")

Func GetRef($sFunc)
    Return Execute($sFunc)
EndFunc



Func Download($hCollection)
    Dim $Result

    $Downloader = $updateSession.CreateUpdateDownloader()
    $Downloader.Updates = $hCollection
    Do
        $DownloadJob = $Downloader.BeginDownload( GetRef("Download_OnProgressChanged"), GetRef("Download_OnCompleted"), "")
        If Not $oMyError.Number = 0 Then
            c("Error " & $oMyError.Number & ": " & $oMyError.Description)
        EndIf

    Until $DownloadJob.IsCompleted
    Sleep(1000)

    $Download = $Downloader.EndDownload($DownloadJob)
EndFunc   ;==>Download




Func Download_OnProgressChanged($hDownloadJob, $hArguments)
    c("Downloading update = " & $hArguments.Progress.PercentComplete)
EndFunc   ;==>Download_OnProgressChanged




Func Download_OnCompleted($hDownloadJob, $hArguments)
    c("Downloading update = 100%")
EndFunc   ;==>Download_OnCompleted

Func MyErrFunc()
    $count += 1
    If $count = 3 Then Exit ; limited to 3 errors and exit to prevent spam (for debug purposes)
  $HexNumber=hex($oMyError.number,8)
  Msgbox(0,"COM Test","We intercepted a COM Error !"       & @CRLF  & @CRLF & _
             "err.description is: "    & @TAB & $oMyError.description    & @CRLF & _
             "err.windescription:"     & @TAB & $oMyError.windescription & @CRLF & _
             "err.number is: "         & @TAB & $HexNumber              & @CRLF & _
             "err.lastdllerror is: "   & @TAB & $oMyError.lastdllerror   & @CRLF & _
             "err.scriptline is: "     & @TAB & $oMyError.scriptline     & @CRLF & _
             "err.source is: "         & @TAB & $oMyError.source         & @CRLF & _
             "err.helpfile is: "       & @TAB & $oMyError.helpfile       & @CRLF & _
             "err.helpcontext is: "    & @TAB & $oMyError.helpcontext _
            )
  SetError(1)   ; to check for after this function returns

Endfunc

I hope it will clarify things much better and If your unsure and you want to do tests before post, I can attach both full scripts as I said earlier.

Sincerely,

WK

Edited by WilliamasKumeliukas
Clarifying a bit more

Sorry if it's quite challenging to understand me sometimes, there is 2 possible reasons to this:

Spoiler

#1. I am a native French speaker and learned English mainly from chatting with others players in online games.

#2. I have a developmental disorder mainly affecting my social abilities, way of thinking, understanding stuffs and explaining myself in which it can seem ironic of seeing me here, but I been working on getting better every days for an dozens of years now ^_^

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Do not like my dirty code? It's fine, but in my opinion, the dirty codes are unique and I believe it's a good glimpse of how the mind of the person who wrote it thinks, and that, that's what I call a psychological deduction step by step in all its splendor.

~WilliamasKumeliukas

Link to post
Share on other sites

no, you didn't make anything clearer

are you trying to bind to events in a browser?

WHAT are you trying to do explicitly, there may be a better way.

you would have to see the code for getref to know how to do it in other languages, if it's possible in autoit even.

 

i still think you don't understand the GetRef function. It returns a Long. looking at your implementation that isn't going to work.

 

Return Value

A Long containing a reference to procname.

Description

Returns a reference to a sub or function. This reference can be used for such purposes as binding to events or defining callback functions.

Rules at a Glance

  • GetRef can be used whenever a function or procedure reference is expected.

  • When using GetRef to define event handlers for events, the Set keyword is required. For example, the code required to bind the Window.OnLoad event to a procedure named ShowGreetingDialog is:

    Set Window.OnLoad = GetRef("ShowGreetingDialog")
Edited by Earthshine

My resources are limited. You must ask the right questions

 

Link to post
Share on other sites

I want to search, download and install windows updates by Creating Object "Microsoft.Update.Session"

21 hours ago, Earthshine said:

no, you didn't make anything clearer

are you trying to bind to events in a browser?

No, I'm not trying to interact or bind to events in a browser, unless Microsoft.Update.Session object is?

Edited by WilliamasKumeliukas

Sorry if it's quite challenging to understand me sometimes, there is 2 possible reasons to this:

Spoiler

#1. I am a native French speaker and learned English mainly from chatting with others players in online games.

#2. I have a developmental disorder mainly affecting my social abilities, way of thinking, understanding stuffs and explaining myself in which it can seem ironic of seeing me here, but I been working on getting better every days for an dozens of years now ^_^

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Do not like my dirty code? It's fine, but in my opinion, the dirty codes are unique and I believe it's a good glimpse of how the mind of the person who wrote it thinks, and that, that's what I call a psychological deduction step by step in all its splendor.

~WilliamasKumeliukas

Link to post
Share on other sites
31 minutes ago, Earthshine said:

no, you didn't make anything clearer

are you trying to bind to events in a browser?

WHAT are you trying to do explicitly, there may be a better way.

you would have to see the code for getref to know how to do it in other languages, if it's possible in autoit even.

 

i still think you don't understand the GetRef function. It returns a Long. looking at your implementation that isn't going to work.

 

Indeed im stuck with a missing specification which I didn't had to specify with vbs code

Sorry if it's quite challenging to understand me sometimes, there is 2 possible reasons to this:

Spoiler

#1. I am a native French speaker and learned English mainly from chatting with others players in online games.

#2. I have a developmental disorder mainly affecting my social abilities, way of thinking, understanding stuffs and explaining myself in which it can seem ironic of seeing me here, but I been working on getting better every days for an dozens of years now ^_^

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Do not like my dirty code? It's fine, but in my opinion, the dirty codes are unique and I believe it's a good glimpse of how the mind of the person who wrote it thinks, and that, that's what I call a psychological deduction step by step in all its splendor.

~WilliamasKumeliukas

Link to post
Share on other sites

Since there is good integration between VBScript and AutoIt, why not run the VBScript code directly (as a VBScript), and then pass data between VBScript and an AutoIt script as needed through ROT objects.

Link to post
Share on other sites

Hello. If you want to use BeginDownload you would probably need to use ObjectFromTag function(search on forum) then create those two objects IDownloadProgressChangedCallback (onProgressChanged) and IDownloadCompletedCallback(onCompleted) and pass the interface pointers to the function.

LarsJ suggestion will be the easier probably better. 

 

Saludos

 

 

 

Link to post
Share on other sites

FWIW, I think my GetRef() is solid.  It returns a bona-fide function pointer when given a valid string.  Just like it does in VBS.

The problem, IMO, is replicating what the VBS Set command does in creating a casted object pointer.

I’m nowhere near as knowledgeable about the COM stuff as others that have already commented, so I’ll leave it to them :)

Code hard, but don’t hard code...

Link to post
Share on other sites
On 9/22/2021 at 3:53 PM, LarsJ said:

Since there is good integration between VBScript and AutoIt, why not run the VBScript code directly (as a VBScript), and then pass data between VBScript and an AutoIt script as needed through ROT objects.

I will take a look onto this, thank you!

13 hours ago, Danyfirex said:

Hello. If you want to use BeginDownload you would probably need to use ObjectFromTag function(search on forum) then create those two objects IDownloadProgressChangedCallback (onProgressChanged) and IDownloadCompletedCallback(onCompleted) and pass the interface pointers to the function.

LarsJ suggestion will be the easier probably better. 

 

Saludos

 

 

 

Thanks for the suggestion! I will check for both suggestion

Regards,

WilliamasKumeliukas

Sorry if it's quite challenging to understand me sometimes, there is 2 possible reasons to this:

Spoiler

#1. I am a native French speaker and learned English mainly from chatting with others players in online games.

#2. I have a developmental disorder mainly affecting my social abilities, way of thinking, understanding stuffs and explaining myself in which it can seem ironic of seeing me here, but I been working on getting better every days for an dozens of years now ^_^

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Do not like my dirty code? It's fine, but in my opinion, the dirty codes are unique and I believe it's a good glimpse of how the mind of the person who wrote it thinks, and that, that's what I call a psychological deduction step by step in all its splendor.

~WilliamasKumeliukas

Link to post
Share on other sites

Hello. Here is the Implementation of ISearchCompletedCallback If You understand how it works you will be able to implement BeginDownload required Interface callbacks.

#include <WinAPICom.au3>

Global Const $S_OK = 0x00000000
Global Const $E_NOINTERFACE = 0x80004002
Global Const $sIID_IUnknown = "{00000000-0000-0000-C000-000000000046}"
Global Const $sIID_SearchCompletedCallback = "{88AEE058-D4B0-4725-A2F1-814A67AE964C}"
Global Const $tagIUnknown = "QueryInterface hresult(ptr;ptr*);" & _
        "AddRef dword();" & _
        "Release dword();"

Global Const $tagIDispatch = $tagIUnknown & _
        "GetTypeInfoCount hresult(dword*);" & _
        "GetTypeInfo hresult(dword;dword;ptr*);" & _
        "GetIDsOfNames hresult(struct*;struct*;dword;dword;struct*);" & _
        "Invoke hresult(uint;struct*;dword;word;struct*;struct*;ptr;uint*);"

Global $oErrorHandler = ObjEvent("AutoIt.Error", "_ErrFunc")


_Test()
Exit

Func _Test()
    _WinAPI_CoInitialize($COINIT_APARTMENTTHREADED)
    Local $oMUS = ObjCreate("Microsoft.Update.Session")
    Local $oSearch = $oMUS.CreateUpdateSearcher()

    Local $oCompleted, $tCompleted
    Local $dtagISearchCompletedCallback = "Invoke hresult(idispatch;ptr);"
    $oCompleted = __ObjectFromTag("__MyInterface_", $dtagISearchCompletedCallback, $tCompleted, Default, $sIID_SearchCompletedCallback)
;~  $oCompleted = __ObjectFromTag("__MyInterface_", $dtagISearchCompletedCallback, $tCompleted)

    Local $AsyncState = "Danyfirex Loves AutoIt"
    Local $sCriteria = "IsInstalled=0 or IsHidden=1 or IsPresent=1"

    ;Create Cast ObjectTag IUpdateSearcher
    Local $sTagSearch = $tagIDispatch & _Dummy("A", "", 8) & "BeginSearch hresult(bstr;ptr;variant;idispatch*);" & "EndSearch hresult(idispatch;idispatch*);"
    Local $oSearchCast = ObjCreateInterface($oSearch, "{8f45abf1-f9ae-4b95-a933-f0f66e5056ea}", $sTagSearch, False)

    Local $oJob = 0
;~  $oJob = $oSearch.BeginSearch($sCriteria, $oCompleted, $Variant) ;this will not work
    $oSearchCast.BeginSearch($sCriteria, $oCompleted(), $AsyncState, $oJob) ;casted to make it work
    ConsoleWrite("$oJob.AsyncState: " & $oJob.AsyncState & @CRLF)

    While Not $oJob.IsCompleted
        Sleep(100)
    WEnd

    MsgBox(0, "ISearchCompletedCallback Invoke Reached", "Print Updates Title & Exit")

    Local $oSearchResult = 0
    $oSearchCast.EndSearch($oJob, $oSearchResult)
    For $oUpdate In $oSearchResult.Updates
        ConsoleWrite(">" & $oUpdate.Title & @CRLF)
    Next

    $oSearchCast = 0
    $oSearch = 0
    $oMUS = 0
EndFunc   ;==>_Test


Func _Dummy($Name, $Parameters = "", $iTimes = 1)
    Local $sTag = ""
    For $i = 1 To $iTimes
        $sTag &= "DM_" & $Name & $i & " hresult(" & $Parameters & ");"
    Next
    Return $sTag
EndFunc   ;==>_Dummy

Func __ObjectFromTag($sFunctionPrefix, $tagInterface, ByRef $tInterface, $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(StringTrimRight(StringReplace(StringRegExpReplace(StringRegExpReplace($tagInterface, "\w+\*", "ptr"), "\h*(\w+)\h*(\w+\*?)\h*(\((.*?)\))\h*(;|;*\z)", "$1\|$2;$4" & @LF), ";" & @LF, @LF), 1), @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]
        ; Replace COM types by matching dllcallback types
        $sTagPart = StringReplace(StringReplace(StringReplace(StringReplace($aSplit[1], "object", "idispatch"), "hresult", "long"), "bstr", "ptr"), "variant", "ptr")
        $sMethod = $sFunctionPrefix & $sNamePart
        $aTagPart = StringSplit($sTagPart, ";", 2)
        $sRet = $aTagPart[0]
        $sParams = StringReplace($sTagPart, $sRet, "", 1)
        $sParams = "ptr" & $sParams
        $hCallback = DllCallbackRegister($sMethod, $sRet, $sParams)
        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

Func __DeleteObjectFromTag(ByRef $tInterface)
    For $i = 1 To DllStructGetData($tInterface, "Size")
        DllCallbackFree(DllStructGetData($tInterface, "Callbacks", $i))
    Next
    $tInterface = 0
EndFunc   ;==>__DeleteObjectFromTag

Func __MyInterface_QueryInterface($pSelf, $pRIID, $pObj)   ; Ret: long  Par: ptr;ptr*
    Local $sIID = StringFromGUID2($pRIID)
    If $sIID = $sIID_IUnknown Then
        DllStructSetData(DllStructCreate("ptr", $pObj), 1, $pSelf)
        Return $S_OK
    ElseIf $sIID = $sIID_SearchCompletedCallback Then
        DllStructSetData(DllStructCreate("ptr", $pObj), 1, $pSelf)
        Return $S_OK
    Else
        Return $E_NOINTERFACE
    EndIf
EndFunc   ;==>__MyInterface_QueryInterface


Func StringFromGUID2($pGUID)
    Local $aReturn = DllCall('ole32.dll', 'int', 'StringFromGUID2', 'struct*', $pGUID, 'wstr', '', 'int', 65536)
    If @error Or Not $aReturn[0] Then Return SetError(@error + 20, @extended, '')
    Return SetExtended($aReturn[0], $aReturn[2])
EndFunc   ;==>StringFromGUID2

Func __MyInterface_AddRef($pSelf)
    Return 1
EndFunc   ;==>__MyInterface_AddRef

Func __MyInterface_Release($pSelf)
    Return 1
EndFunc   ;==>__MyInterface_Release

Volatile Func __MyInterface_Invoke($pSelf, $oSearchJob, $pISearchCompletedCallbackArgs)
    ConsoleWrite("Invoke" & @CRLF)
    ConsoleWrite("Invoke - oSearchJob.AsyncState: " & $oSearchJob.AsyncState & @CRLF)
    Return $S_OK
EndFunc   ;==>__MyInterface_Invoke

; User's COM error function. Will be called if COM error occurs
Func _ErrFunc($oError)
    ; Do anything here.
    ConsoleWrite(@ScriptName & " (" & $oError.scriptline & ") : ==> COM Error intercepted !" & @CRLF & _
            @TAB & "err.number is: " & @TAB & @TAB & "0x" & Hex($oError.number) & @CRLF & _
            @TAB & "err.windescription:" & @TAB & $oError.windescription & @CRLF & _
            @TAB & "err.description is: " & @TAB & $oError.description & @CRLF & _
            @TAB & "err.source is: " & @TAB & @TAB & $oError.source & @CRLF & _
            @TAB & "err.helpfile is: " & @TAB & $oError.helpfile & @CRLF & _
            @TAB & "err.helpcontext is: " & @TAB & $oError.helpcontext & @CRLF & _
            @TAB & "err.lastdllerror is: " & @TAB & $oError.lastdllerror & @CRLF & _
            @TAB & "err.scriptline is: " & @TAB & $oError.scriptline & @CRLF & _
            @TAB & "err.retcode is: " & @TAB & "0x" & Hex($oError.retcode) & @CRLF & @CRLF)
EndFunc   ;==>_ErrFunc

 

Saludos

Link to post
Share on other sites
  • Melba23 changed the title to Convert GetRef function from VBScript to AutoIt

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...