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
23 minutes ago, WilliamasKumeliukas said:

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

No, I had only read it after it was declared impossible and subject changed to “removed”.

Please repost.

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

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
  • Melba23 changed the title to Convert GetRef function from VBScript to AutoIt

Hello. It's me again. Just to leave a whole example. 

#RequireAdmin
#include <WinAPICom.au3>
#include <Debug.au3>
#include <Array.au3>

Global Const $S_OK = 0x00000000
Global Const $E_NOINTERFACE = 0x80004002
Global Const $sIID_IUnknown = "{00000000-0000-0000-C000-000000000046}"
Global Const $sIID_ISearchCompletedCallback = "{88AEE058-D4B0-4725-A2F1-814A67AE964C}"
Global Const $sIID_IDownloadCompletedCallback = "{77254866-9F5B-4C8E-B9E2-C77A8530D64B}"
Global Const $sIID_IDownloadProgressChangedCallback = "{8C3F1CDD-6173-4591-AEBD-A56A53CA77C1}"

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")
Global $g_aSelectedRows = 0

_Test()
Exit

Func _Test()
    _WinAPI_CoInitialize($COINIT_APARTMENTTHREADED)

    Local Const $sCriteria = "Type='Software' and IsInstalled=0"
    Local $oMUS = ObjCreate("Microsoft.Update.Session")
    Local $oSearcher = $oMUS.CreateUpdateSearcher()

    Local $oCompleted, $tCompleted, $dtagISearchCompletedCallback = "InvokeSCC hresult(idispatch;ptr);"
    $oCompleted = __ObjectFromTag("__MyInterface_", $dtagISearchCompletedCallback, $tCompleted)

    ;Create Cast Tag IUpdateSearcher
    Local $sTagSearcher = $tagIDispatch & _Dummy("A", "", 8) & "BeginSearch hresult(bstr;ptr;variant;idispatch*);" & "EndSearch hresult(idispatch;idispatch*);"
    Local $oSearcherCast = ObjCreateInterface($oSearcher, "{8F45ABF1-F9AE-4B95-A933-F0F66E5056EA}", $sTagSearcher, False)

    Local $AsyncState = "Danyfirex Loves AutoIt"
    Local $oJob = 0
;~  $oJob = $oSearcher.BeginSearch($sCriteria, $oCompleted, $Variant) ;this will not work
    $oSearcherCast.BeginSearch($sCriteria, $oCompleted(), $AsyncState, $oJob) ;casted to make it work

    While Not $oJob.IsCompleted ;wait search
        Sleep(100)
    WEnd

    Local $oSearchResult = 0
    $oSearcherCast.EndSearch($oJob, $oSearchResult)
    Local $aUpdates[$oSearchResult.Updates.Count][5]
    Local $oCustomUpdateCollection = $oSearchResult.Updates.Copy
    $oCustomUpdateCollection.Clear
    Local $iCount = 0
    For $oUpdate In $oSearchResult.Updates
        $aUpdates[$iCount][0] = $oUpdate.Title
        $aUpdates[$iCount][1] = $oUpdate.Description
        $aUpdates[$iCount][2] = ByteSuffix($oUpdate.MaxDownloadSize)
        $aUpdates[$iCount][3] = $oUpdate.MaxDownloadSize
        $aUpdates[$iCount][4] = $oUpdate
        $iCount += 1
    Next

    _ArraySort($aUpdates, 0, 0, 0, 3)
    _DebugArrayDisplay($aUpdates, "Select Some Updates for Download Click ""Run User Func""", "|0:3", 0, Default, "Title|Description|Size|Size Bytes", Default, _GetSelected)

    If $g_aSelectedRows[0] = 0 Then
        Return MsgBox(0, "Info", "No Updates Selected. Script will Exit...")
    EndIf

    ;Create Update Collection
    For $i = 1 To $g_aSelectedRows[0]
        ConsoleWrite("Add Update: " & $aUpdates[$g_aSelectedRows[$i]][0] & @CRLF)
        $oCustomUpdateCollection.Add($aUpdates[$g_aSelectedRows[$i]][4])
    Next

    Local $oDownloader = $oMUS.CreateUpdateDownloader()
    $oDownloader.Updates = $oCustomUpdateCollection

    Local $sTagDownloader = $tagIDispatch & _Dummy("A", "", 8) & "BeginDownload hresult(ptr;ptr;variant;idispatch*);Download hresult();EndDownload hresult(idispatch;idispatch*);"
    Local $oDownloaderCast = ObjCreateInterface($oDownloader, "{68F1C6F9-7ECC-4666-A464-247FE12496C3}", $sTagDownloader, False)

    Local $oDownloadProgress, $tDownloadProgress, $dtagIDownloadProgressChangedCallback = "Invoke_DPCC hresult(idispatch;idispatch);"
    $oDownloadProgress = __ObjectFromTag("__MyInterface_", $dtagIDownloadProgressChangedCallback, $tDownloadProgress)

    Local $oDownloadCompleted, $tDownloadCompleted, $dtagIDownloadCompletedCallback = "Invoke_DCC hresult(idispatch;ptr);"
    $oDownloadCompleted = __ObjectFromTag("__MyInterface_", $dtagIDownloadCompletedCallback, $tDownloadCompleted)


    Local $AsyncState = "Danyfirex Loves AutoIt Download"
    Local $oDownloadJob = 0
;~  $oDownloader.BeginDownload($oDownloadProgress(), $oDownloadCompleted(), $AsyncState, $oDownloadJob) ;this will not work
    $oDownloaderCast.BeginDownload($oDownloadProgress(), $oDownloadCompleted(), $AsyncState, $oDownloadJob) ;casted to make it work
    ProgressOn("Downloading Updates", "Download Started...")

    While Not $oDownloadJob.IsCompleted
        Sleep(100)
    WEnd

    Sleep(2000)
    ProgressOff()

    Local $oDownloadResult = 0
    $oDownloaderCast.EndDownload($oDownloadJob, $oDownloadResult)
    If $oDownloadResult.ResultCode = 2 Then
        MsgBox(0, "Info", "Download Completed.")
    Else
        MsgBox(0, "Info", "Download Failed.")
    EndIf

    $oDownloader = 0
    $oDownloaderCast = 0
    $oSearcherCast = 0
    $oSearcher = 0
    $oMUS = 0
EndFunc   ;==>_Test

Func _GetSelected($aArray, $aSelected)
    $g_aSelectedRows = $aSelected
    If $g_aSelectedRows[0] = 0 Then
        MsgBox(0, "", "Select one/more items. Click ""Run User Func""")
    Else
        Send("{ESC}")
    EndIf
EndFunc   ;==>_GetSelected


Func ByteSuffix($iBytes)
    Local $iIndex = 0, $aArray = [' bytes', ' KB', ' MB', ' GB', ' TB', ' PB', ' EB', ' ZB', ' YB']
    While $iBytes > 1023
        $iIndex += 1
        $iBytes /= 1024
    WEnd
    Return Round($iBytes) & $aArray[$iIndex]
EndFunc   ;==>ByteSuffix

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_ISearchCompletedCallback Then
        DllStructSetData(DllStructCreate("ptr", $pObj), 1, $pSelf)
        Return $S_OK
    ElseIf $sIID = $sIID_IDownloadCompletedCallback Then
        DllStructSetData(DllStructCreate("ptr", $pObj), 1, $pSelf)
        Return $S_OK
    ElseIf $sIID = $sIID_IDownloadProgressChangedCallback Then
        DllStructSetData(DllStructCreate("ptr", $pObj), 1, $pSelf)
        Return $S_OK
    Else
        Return $E_NOINTERFACE
    EndIf
EndFunc   ;==>__MyInterface_QueryInterface

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

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

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

Volatile Func __MyInterface_Invoke_DCC($pSelf, $oDownloadJob, $pIDownloadCompletedCallbackArgs)
;~  ConsoleWrite("InvokeDCC - $oDownloadJob.AsyncState: " & $oDownloadJob.AsyncState & @CRLF)
    ProgressSet(100, "Download Completed...", "Download Completed.")
    Return $S_OK
EndFunc   ;==>__MyInterface_Invoke_DCC

Volatile Func __MyInterface_Invoke_DPCC($pSelf, $oDownloadJob, $oDownloadProgressChangedCallbackArgs)
;~  ConsoleWrite("InvokeDPCC" & @CRLF)
    Local $iCurrentPercent = $oDownloadProgressChangedCallbackArgs.Progress.CurrentUpdatePercentComplete
    ProgressSet($iCurrentPercent, "(" & $iCurrentPercent & "%) " & $oDownloadJob.Updates($oDownloadProgressChangedCallbackArgs.Progress.CurrentUpdateIndex).Title, _
            "Downloading Updates (" & $oDownloadProgressChangedCallbackArgs.Progress.CurrentUpdateIndex + 1 & "/" & $oDownloadJob.Updates.Count & ")")
    Return $S_OK
EndFunc   ;==>__MyInterface_Invoke_DPCC

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

; 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

uff... now I know why my computer do not want to install recent update

image.png.472d5d6a8bd28bd98365164b31472966.png

 

Because I do not have 100GB free space on my SSD
 

Edited by mLipok

Signature beginning:
Please remember: "AutoIt"..... *  Wondering who uses AutoIt and what it can be used for ? * Forum Rules *
ADO.au3 UDF * POP3.au3 UDF * XML.au3 UDF * for other useful stuff click the following button:

Spoiler

Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind. 

My contribution (my own projects): * Debenu Quick PDF Library - UDF * Debenu PDF Viewer SDK - UDF * Acrobat Reader - ActiveX Viewer * UDF for PDFCreator v1.x.x * XZip - UDF * AppCompatFlags UDF * CrowdinAPI UDF * _WinMergeCompare2Files() * _JavaExceptionAdd() * _IsBeta() * Writing DPI Awareness App - workaround * _AutoIt_RequiredVersion() * Chilkatsoft.au3 UDF * TeamViewer.au3 UDF * JavaManagement UDF * VIES over SOAP * WinSCP UDF * GHAPI UDF - modest begining - comunication with GitHub REST APIErrorLog.au3 UDF - A logging Library * Include Dependency Tree (Tool for analyzing script relations) *

My contribution to others projects or UDF based on  others projects: * _sql.au3 UDF  * POP3.au3 UDF *  RTF Printer - UDF * XML.au3 UDF * ADO.au3 UDF SMTP Mailer UDF * Dual Monitor resolution detection * * 2GUI on Dual Monitor System * _SciLexer.au3 UDF * SciTE - Lexer for console pane

Useful links: * Forum Rules * Forum etiquette *  Forum Information and FAQs * How to post code on the forum * AutoIt Online Documentation * AutoIt Online Beta Documentation * SciTE4AutoIt3 getting started * Convert text blocks to AutoIt code * Games made in Autoit * Programming related sites * Polish AutoIt Tutorial * DllCall Code Generator * 

Wiki: Expand your knowledge - AutoIt Wiki * Collection of User Defined Functions * How to use HelpFile * Good coding practices in AutoIt * 

OpenOffice/LibreOffice/XLS Related: WriterDemo.au3 * XLS/MDB from scratch with ADOX

IE Related:  * How to use IE.au3  UDF with  AutoIt v3.3.14.x * Why isn't Autoit able to click a Javascript Dialog? * Clicking javascript button with no ID * IE document >> save as MHT file * IETab Switcher (by LarsJ ) * HTML Entities * _IEquerySelectorAll() (by uncommon) * IE in TaskSchedulerIE Embedded Control Versioning (use IE9+ and HTML5 in a GUI) * PDF Related:How to get reference to PDF object embeded in IE *

I encourage you to read: * Global Vars * Best Coding Practices * Please explain code used in Help file for several File functions * OOP-like approach in AutoIt * UDF-Spec Questions *  EXAMPLE: How To Catch ConsoleWrite() output to a file or to CMD *

I also encourage you to check awesome @trancexx code:  * Create COM objects from modules without any demand on user to register anything. * Another COM object registering stuffOnHungApp handlerAvoid "AutoIt Error" message box in unknown errors  * HTML editor

winhttp.au3 related : * https://www.autoitscript.com/forum/topic/206771-winhttpau3-download-problem-youre-speaking-plain-http-to-an-ssl-enabled-server-port/

"Homo sum; humani nil a me alienum puto" - Publius Terentius Afer
"Program are meant to be read by humans and only incidentally for computers and execute" - Donald Knuth, "The Art of Computer Programming"
:naughty:  :ranting:, be  :) and       \\//_.

Anticipating Errors :  "Any program that accepts data from a user must include code to validate that data before sending it to the data store. You cannot rely on the data store, ...., or even your programming language to notify you of problems. You must check every byte entered by your users, making sure that data is the correct type for its field and that required fields are not empty."

Signature last update: 2021-10-18

Link to post
Share on other sites

Here is little modified script (compatibility with Au3Check) :

;~ https://www.autoitscript.com/forum/topic/206615-convert-getref-function-from-vbscript-to-autoit/?tab=comments#comment-1489832

#RequireAdmin
#include <WinAPICom.au3>
#include <Debug.au3>
#include <Array.au3>

Global Const $S_OK = 0x00000000
Global Const $E_NOINTERFACE = 0x80004002
Global Const $sIID_IUnknown = "{00000000-0000-0000-C000-000000000046}"
Global Const $sIID_ISearchCompletedCallback = "{88AEE058-D4B0-4725-A2F1-814A67AE964C}"
Global Const $sIID_IDownloadCompletedCallback = "{77254866-9F5B-4C8E-B9E2-C77A8530D64B}"
Global Const $sIID_IDownloadProgressChangedCallback = "{8C3F1CDD-6173-4591-AEBD-A56A53CA77C1}"

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")
Global $g_aSelectedRows = 0

_Test()
Exit

Func _Test()
    _WinAPI_CoInitialize($COINIT_APARTMENTTHREADED)

    Local Const $sCriteria = "Type='Software' and IsInstalled=0"
    Local $oMUS = ObjCreate("Microsoft.Update.Session")
    Local $oSearcher = $oMUS.CreateUpdateSearcher()

    Local $oCompleted, $tCompleted, $dtagISearchCompletedCallback = "InvokeSCC hresult(idispatch;ptr);"
    $oCompleted = __ObjectFromTag("__MyInterface_", $dtagISearchCompletedCallback, $tCompleted)

    ;Create Cast Tag IUpdateSearcher
    Local $sTagSearcher = $tagIDispatch & _Dummy("A", "", 8) & "BeginSearch hresult(bstr;ptr;variant;idispatch*);" & "EndSearch hresult(idispatch;idispatch*);"
    Local $oSearcherCast = ObjCreateInterface($oSearcher, "{8F45ABF1-F9AE-4B95-A933-F0F66E5056EA}", $sTagSearcher, False)

    Local $AsyncState = "Danyfirex Loves AutoIt"
    Local $oJob = 0
;~  $oJob = $oSearcher.BeginSearch($sCriteria, $oCompleted, $Variant) ;this will not work
    $oSearcherCast.BeginSearch($sCriteria, $oCompleted(), $AsyncState, $oJob) ;casted to make it work

    While Not $oJob.IsCompleted ;wait search
        Sleep(100)
    WEnd

    Local $oSearchResult = 0
    $oSearcherCast.EndSearch($oJob, $oSearchResult)
    Local $aUpdates[$oSearchResult.Updates.Count][5]
    Local $oCustomUpdateCollection = $oSearchResult.Updates.Copy
    $oCustomUpdateCollection.Clear
    Local $iCount = 0
    For $oUpdate In $oSearchResult.Updates
        $aUpdates[$iCount][0] = $oUpdate.Title
        $aUpdates[$iCount][1] = $oUpdate.Description
        $aUpdates[$iCount][2] = ByteSuffix($oUpdate.MaxDownloadSize)
        $aUpdates[$iCount][3] = $oUpdate.MaxDownloadSize
        $aUpdates[$iCount][4] = $oUpdate
        $iCount += 1
    Next

    _ArraySort($aUpdates, 0, 0, 0, 3)
    _DebugArrayDisplay($aUpdates, "Select Some Updates for Download Click ""Run User Func""", "|0:3", 0, Default, "Title|Description|Size|Size Bytes", Default, _GetSelected)

    If $g_aSelectedRows[0] = 0 Then
        Return MsgBox(0, "Info", "No Updates Selected. Script will Exit...")
    EndIf

    ;Create Update Collection
    For $i = 1 To $g_aSelectedRows[0]
        ConsoleWrite("Add Update: " & $aUpdates[$g_aSelectedRows[$i]][0] & @CRLF)
        $oCustomUpdateCollection.Add($aUpdates[$g_aSelectedRows[$i]][4])
    Next

    Local $oDownloader = $oMUS.CreateUpdateDownloader()
    $oDownloader.Updates = $oCustomUpdateCollection

    Local $sTagDownloader = $tagIDispatch & _Dummy("A", "", 8) & "BeginDownload hresult(ptr;ptr;variant;idispatch*);Download hresult();EndDownload hresult(idispatch;idispatch*);"
    Local $oDownloaderCast = ObjCreateInterface($oDownloader, "{68F1C6F9-7ECC-4666-A464-247FE12496C3}", $sTagDownloader, False)

    Local $oDownloadProgress, $tDownloadProgress, $dtagIDownloadProgressChangedCallback = "Invoke_DPCC hresult(idispatch;idispatch);"
    $oDownloadProgress = __ObjectFromTag("__MyInterface_", $dtagIDownloadProgressChangedCallback, $tDownloadProgress)

    Local $oDownloadCompleted, $tDownloadCompleted, $dtagIDownloadCompletedCallback = "Invoke_DCC hresult(idispatch;ptr);"
    $oDownloadCompleted = __ObjectFromTag("__MyInterface_", $dtagIDownloadCompletedCallback, $tDownloadCompleted)


    $AsyncState = "Danyfirex Loves AutoIt Download"
    Local $oDownloadJob = 0
;~  $oDownloader.BeginDownload($oDownloadProgress(), $oDownloadCompleted(), $AsyncState, $oDownloadJob) ;this will not work
    $oDownloaderCast.BeginDownload($oDownloadProgress(), $oDownloadCompleted(), $AsyncState, $oDownloadJob) ;casted to make it work
    ProgressOn("Downloading Updates", "Download Started...")

    While Not $oDownloadJob.IsCompleted
        Sleep(100)
    WEnd

    Sleep(2000)
    ProgressOff()

    Local $oDownloadResult = 0
    $oDownloaderCast.EndDownload($oDownloadJob, $oDownloadResult)
    If $oDownloadResult.ResultCode = 2 Then
        MsgBox(0, "Info", "Download Completed.")
    Else
        MsgBox(0, "Info", "Download Failed.")
    EndIf

    $oDownloader = 0
    $oDownloaderCast = 0
    $oSearcherCast = 0
    $oSearcher = 0
    $oMUS = 0
EndFunc   ;==>_Test

Func _GetSelected($aArray, $aSelected)
    #forceref $aArray
    $g_aSelectedRows = $aSelected
    If $g_aSelectedRows[0] = 0 Then
        MsgBox(0, "", "Select one/more items. Click ""Run User Func""")
    Else
        Send("{ESC}")
    EndIf
EndFunc   ;==>_GetSelected


Func ByteSuffix($iBytes)
    Local $iIndex = 0, $aArray = [' bytes', ' KB', ' MB', ' GB', ' TB', ' PB', ' EB', ' ZB', ' YB']
    While $iBytes > 1023
        $iIndex += 1
        $iBytes /= 1024
    WEnd
    Return Round($iBytes) & $aArray[$iIndex]
EndFunc   ;==>ByteSuffix

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_ISearchCompletedCallback Then
        DllStructSetData(DllStructCreate("ptr", $pObj), 1, $pSelf)
        Return $S_OK
    ElseIf $sIID = $sIID_IDownloadCompletedCallback Then
        DllStructSetData(DllStructCreate("ptr", $pObj), 1, $pSelf)
        Return $S_OK
    ElseIf $sIID = $sIID_IDownloadProgressChangedCallback Then
        DllStructSetData(DllStructCreate("ptr", $pObj), 1, $pSelf)
        Return $S_OK
    Else
        Return $E_NOINTERFACE
    EndIf
EndFunc   ;==>__MyInterface_QueryInterface

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

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

Volatile Func __MyInterface_Invoke_SCC($pSelf, $oSearchJob, $pISearchCompletedCallbackArgs)
    #forceref $pSelf, $oSearchJob, $pISearchCompletedCallbackArgs
;~  ConsoleWrite("InvokeSCC - oSearchJob.AsyncState: " & $oSearchJob.AsyncState & @CRLF)
    Return $S_OK
EndFunc   ;==>__MyInterface_Invoke_SCC

Volatile Func __MyInterface_Invoke_DCC($pSelf, $oDownloadJob, $pIDownloadCompletedCallbackArgs)
    #forceref $pSelf, $oDownloadJob, $pIDownloadCompletedCallbackArgs
;~  ConsoleWrite("InvokeDCC - $oDownloadJob.AsyncState: " & $oDownloadJob.AsyncState & @CRLF)
    ProgressSet(100, "Download Completed...", "Download Completed.")
    Return $S_OK
EndFunc   ;==>__MyInterface_Invoke_DCC

Volatile Func __MyInterface_Invoke_DPCC($pSelf, $oDownloadJob, $oDownloadProgressChangedCallbackArgs)
    #forceref $pSelf
;~  ConsoleWrite("InvokeDPCC" & @CRLF)
    Local $iCurrentPercent = $oDownloadProgressChangedCallbackArgs.Progress.CurrentUpdatePercentComplete
    ProgressSet($iCurrentPercent, "(" & $iCurrentPercent & "%) " & $oDownloadJob.Updates($oDownloadProgressChangedCallbackArgs.Progress.CurrentUpdateIndex).Title, _
            "Downloading Updates (" & $oDownloadProgressChangedCallbackArgs.Progress.CurrentUpdateIndex + 1 & "/" & $oDownloadJob.Updates.Count & ")")
    Return $S_OK
EndFunc   ;==>__MyInterface_Invoke_DPCC

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

; 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

 

Even after my mod, I still get:

Quote

 Subscript used on non-accessible variable.:
If $g_aSelectedRows[0] = 0 Then
If $g_aSelectedRows^ ERROR

related to this:
 

If $g_aSelectedRows[0] = 0 Then
        Return MsgBox(0, "Info", "No Updates Selected. Script will Exit...")
    EndIf

 

Edited by mLipok

Signature beginning:
Please remember: "AutoIt"..... *  Wondering who uses AutoIt and what it can be used for ? * Forum Rules *
ADO.au3 UDF * POP3.au3 UDF * XML.au3 UDF * for other useful stuff click the following button:

Spoiler

Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind. 

My contribution (my own projects): * Debenu Quick PDF Library - UDF * Debenu PDF Viewer SDK - UDF * Acrobat Reader - ActiveX Viewer * UDF for PDFCreator v1.x.x * XZip - UDF * AppCompatFlags UDF * CrowdinAPI UDF * _WinMergeCompare2Files() * _JavaExceptionAdd() * _IsBeta() * Writing DPI Awareness App - workaround * _AutoIt_RequiredVersion() * Chilkatsoft.au3 UDF * TeamViewer.au3 UDF * JavaManagement UDF * VIES over SOAP * WinSCP UDF * GHAPI UDF - modest begining - comunication with GitHub REST APIErrorLog.au3 UDF - A logging Library * Include Dependency Tree (Tool for analyzing script relations) *

My contribution to others projects or UDF based on  others projects: * _sql.au3 UDF  * POP3.au3 UDF *  RTF Printer - UDF * XML.au3 UDF * ADO.au3 UDF SMTP Mailer UDF * Dual Monitor resolution detection * * 2GUI on Dual Monitor System * _SciLexer.au3 UDF * SciTE - Lexer for console pane

Useful links: * Forum Rules * Forum etiquette *  Forum Information and FAQs * How to post code on the forum * AutoIt Online Documentation * AutoIt Online Beta Documentation * SciTE4AutoIt3 getting started * Convert text blocks to AutoIt code * Games made in Autoit * Programming related sites * Polish AutoIt Tutorial * DllCall Code Generator * 

Wiki: Expand your knowledge - AutoIt Wiki * Collection of User Defined Functions * How to use HelpFile * Good coding practices in AutoIt * 

OpenOffice/LibreOffice/XLS Related: WriterDemo.au3 * XLS/MDB from scratch with ADOX

IE Related:  * How to use IE.au3  UDF with  AutoIt v3.3.14.x * Why isn't Autoit able to click a Javascript Dialog? * Clicking javascript button with no ID * IE document >> save as MHT file * IETab Switcher (by LarsJ ) * HTML Entities * _IEquerySelectorAll() (by uncommon) * IE in TaskSchedulerIE Embedded Control Versioning (use IE9+ and HTML5 in a GUI) * PDF Related:How to get reference to PDF object embeded in IE *

I encourage you to read: * Global Vars * Best Coding Practices * Please explain code used in Help file for several File functions * OOP-like approach in AutoIt * UDF-Spec Questions *  EXAMPLE: How To Catch ConsoleWrite() output to a file or to CMD *

I also encourage you to check awesome @trancexx code:  * Create COM objects from modules without any demand on user to register anything. * Another COM object registering stuffOnHungApp handlerAvoid "AutoIt Error" message box in unknown errors  * HTML editor

winhttp.au3 related : * https://www.autoitscript.com/forum/topic/206771-winhttpau3-download-problem-youre-speaking-plain-http-to-an-ssl-enabled-server-port/

"Homo sum; humani nil a me alienum puto" - Publius Terentius Afer
"Program are meant to be read by humans and only incidentally for computers and execute" - Donald Knuth, "The Art of Computer Programming"
:naughty:  :ranting:, be  :) and       \\//_.

Anticipating Errors :  "Any program that accepts data from a user must include code to validate that data before sending it to the data store. You cannot rely on the data store, ...., or even your programming language to notify you of problems. You must check every byte entered by your users, making sure that data is the correct type for its field and that required fields are not empty."

Signature last update: 2021-10-18

Link to post
Share on other sites
18 minutes ago, Danyfirex said:

Hello. It's me again. Just to leave a whole example. 

#RequireAdmin
#include <WinAPICom.au3>
#include <Debug.au3>
#include <Array.au3>

Global Const $S_OK = 0x00000000
Global Const $E_NOINTERFACE = 0x80004002
Global Const $sIID_IUnknown = "{00000000-0000-0000-C000-000000000046}"
Global Const $sIID_ISearchCompletedCallback = "{88AEE058-D4B0-4725-A2F1-814A67AE964C}"
Global Const $sIID_IDownloadCompletedCallback = "{77254866-9F5B-4C8E-B9E2-C77A8530D64B}"
Global Const $sIID_IDownloadProgressChangedCallback = "{8C3F1CDD-6173-4591-AEBD-A56A53CA77C1}"

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")
Global $g_aSelectedRows = 0

_Test()
Exit

Func _Test()
    _WinAPI_CoInitialize($COINIT_APARTMENTTHREADED)

    Local Const $sCriteria = "Type='Software' and IsInstalled=0"
    Local $oMUS = ObjCreate("Microsoft.Update.Session")
    Local $oSearcher = $oMUS.CreateUpdateSearcher()

    Local $oCompleted, $tCompleted, $dtagISearchCompletedCallback = "InvokeSCC hresult(idispatch;ptr);"
    $oCompleted = __ObjectFromTag("__MyInterface_", $dtagISearchCompletedCallback, $tCompleted)

    ;Create Cast Tag IUpdateSearcher
    Local $sTagSearcher = $tagIDispatch & _Dummy("A", "", 8) & "BeginSearch hresult(bstr;ptr;variant;idispatch*);" & "EndSearch hresult(idispatch;idispatch*);"
    Local $oSearcherCast = ObjCreateInterface($oSearcher, "{8F45ABF1-F9AE-4B95-A933-F0F66E5056EA}", $sTagSearcher, False)

    Local $AsyncState = "Danyfirex Loves AutoIt"
    Local $oJob = 0
;~  $oJob = $oSearcher.BeginSearch($sCriteria, $oCompleted, $Variant) ;this will not work
    $oSearcherCast.BeginSearch($sCriteria, $oCompleted(), $AsyncState, $oJob) ;casted to make it work

    While Not $oJob.IsCompleted ;wait search
        Sleep(100)
    WEnd

    Local $oSearchResult = 0
    $oSearcherCast.EndSearch($oJob, $oSearchResult)
    Local $aUpdates[$oSearchResult.Updates.Count][5]
    Local $oCustomUpdateCollection = $oSearchResult.Updates.Copy
    $oCustomUpdateCollection.Clear
    Local $iCount = 0
    For $oUpdate In $oSearchResult.Updates
        $aUpdates[$iCount][0] = $oUpdate.Title
        $aUpdates[$iCount][1] = $oUpdate.Description
        $aUpdates[$iCount][2] = ByteSuffix($oUpdate.MaxDownloadSize)
        $aUpdates[$iCount][3] = $oUpdate.MaxDownloadSize
        $aUpdates[$iCount][4] = $oUpdate
        $iCount += 1
    Next

    _ArraySort($aUpdates, 0, 0, 0, 3)
    _DebugArrayDisplay($aUpdates, "Select Some Updates for Download Click ""Run User Func""", "|0:3", 0, Default, "Title|Description|Size|Size Bytes", Default, _GetSelected)

    If $g_aSelectedRows[0] = 0 Then
        Return MsgBox(0, "Info", "No Updates Selected. Script will Exit...")
    EndIf

    ;Create Update Collection
    For $i = 1 To $g_aSelectedRows[0]
        ConsoleWrite("Add Update: " & $aUpdates[$g_aSelectedRows[$i]][0] & @CRLF)
        $oCustomUpdateCollection.Add($aUpdates[$g_aSelectedRows[$i]][4])
    Next

    Local $oDownloader = $oMUS.CreateUpdateDownloader()
    $oDownloader.Updates = $oCustomUpdateCollection

    Local $sTagDownloader = $tagIDispatch & _Dummy("A", "", 8) & "BeginDownload hresult(ptr;ptr;variant;idispatch*);Download hresult();EndDownload hresult(idispatch;idispatch*);"
    Local $oDownloaderCast = ObjCreateInterface($oDownloader, "{68F1C6F9-7ECC-4666-A464-247FE12496C3}", $sTagDownloader, False)

    Local $oDownloadProgress, $tDownloadProgress, $dtagIDownloadProgressChangedCallback = "Invoke_DPCC hresult(idispatch;idispatch);"
    $oDownloadProgress = __ObjectFromTag("__MyInterface_", $dtagIDownloadProgressChangedCallback, $tDownloadProgress)

    Local $oDownloadCompleted, $tDownloadCompleted, $dtagIDownloadCompletedCallback = "Invoke_DCC hresult(idispatch;ptr);"
    $oDownloadCompleted = __ObjectFromTag("__MyInterface_", $dtagIDownloadCompletedCallback, $tDownloadCompleted)


    Local $AsyncState = "Danyfirex Loves AutoIt Download"
    Local $oDownloadJob = 0
;~  $oDownloader.BeginDownload($oDownloadProgress(), $oDownloadCompleted(), $AsyncState, $oDownloadJob) ;this will not work
    $oDownloaderCast.BeginDownload($oDownloadProgress(), $oDownloadCompleted(), $AsyncState, $oDownloadJob) ;casted to make it work
    ProgressOn("Downloading Updates", "Download Started...")

    While Not $oDownloadJob.IsCompleted
        Sleep(100)
    WEnd

    Sleep(2000)
    ProgressOff()

    Local $oDownloadResult = 0
    $oDownloaderCast.EndDownload($oDownloadJob, $oDownloadResult)
    If $oDownloadResult.ResultCode = 2 Then
        MsgBox(0, "Info", "Download Completed.")
    Else
        MsgBox(0, "Info", "Download Failed.")
    EndIf

    $oDownloader = 0
    $oDownloaderCast = 0
    $oSearcherCast = 0
    $oSearcher = 0
    $oMUS = 0
EndFunc   ;==>_Test

Func _GetSelected($aArray, $aSelected)
    $g_aSelectedRows = $aSelected
    If $g_aSelectedRows[0] = 0 Then
        MsgBox(0, "", "Select one/more items. Click ""Run User Func""")
    Else
        Send("{ESC}")
    EndIf
EndFunc   ;==>_GetSelected


Func ByteSuffix($iBytes)
    Local $iIndex = 0, $aArray = [' bytes', ' KB', ' MB', ' GB', ' TB', ' PB', ' EB', ' ZB', ' YB']
    While $iBytes > 1023
        $iIndex += 1
        $iBytes /= 1024
    WEnd
    Return Round($iBytes) & $aArray[$iIndex]
EndFunc   ;==>ByteSuffix

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_ISearchCompletedCallback Then
        DllStructSetData(DllStructCreate("ptr", $pObj), 1, $pSelf)
        Return $S_OK
    ElseIf $sIID = $sIID_IDownloadCompletedCallback Then
        DllStructSetData(DllStructCreate("ptr", $pObj), 1, $pSelf)
        Return $S_OK
    ElseIf $sIID = $sIID_IDownloadProgressChangedCallback Then
        DllStructSetData(DllStructCreate("ptr", $pObj), 1, $pSelf)
        Return $S_OK
    Else
        Return $E_NOINTERFACE
    EndIf
EndFunc   ;==>__MyInterface_QueryInterface

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

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

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

Volatile Func __MyInterface_Invoke_DCC($pSelf, $oDownloadJob, $pIDownloadCompletedCallbackArgs)
;~  ConsoleWrite("InvokeDCC - $oDownloadJob.AsyncState: " & $oDownloadJob.AsyncState & @CRLF)
    ProgressSet(100, "Download Completed...", "Download Completed.")
    Return $S_OK
EndFunc   ;==>__MyInterface_Invoke_DCC

Volatile Func __MyInterface_Invoke_DPCC($pSelf, $oDownloadJob, $oDownloadProgressChangedCallbackArgs)
;~  ConsoleWrite("InvokeDPCC" & @CRLF)
    Local $iCurrentPercent = $oDownloadProgressChangedCallbackArgs.Progress.CurrentUpdatePercentComplete
    ProgressSet($iCurrentPercent, "(" & $iCurrentPercent & "%) " & $oDownloadJob.Updates($oDownloadProgressChangedCallbackArgs.Progress.CurrentUpdateIndex).Title, _
            "Downloading Updates (" & $oDownloadProgressChangedCallbackArgs.Progress.CurrentUpdateIndex + 1 & "/" & $oDownloadJob.Updates.Count & ")")
    Return $S_OK
EndFunc   ;==>__MyInterface_Invoke_DPCC

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

; 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

Omg @Danyfirex, your incredible! :D I cannot thank you enough for this great help! 

 

12 minutes ago, mLipok said:

uff... no I know why my computer do not want to install recent update

image.png.472d5d6a8bd28bd98365164b31472966.png

 

Because I do not have 100GB free space on my SSD
 

@mLipok, this is a normal bug from Microsoft, I most of the time get this 100gb update for each culmulative updates (via microsoft update session), this is a miscalculation which is not actually downloading 103gb for real

Edited by WilliamasKumeliukas
typos

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

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