Jump to content

Recommended Posts

Posted (edited)

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:

  Reveal hidden contents
Posted (edited)
  On 9/17/2021 at 9:47 PM, JockoDundee said:

why not:

Func GetRef($sFunc)

   Return Execute($sFunc)

EndFunc

 

Expand  

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:

  Reveal hidden contents
Posted (edited)

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

 

Posted (edited)
  On 9/22/2021 at 1:58 PM, 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?

 

 

Expand  

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:

  Reveal hidden contents
Posted (edited)

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

 

Posted (edited)

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

  On 9/22/2021 at 3:57 PM, Earthshine said:

no, you didn't make anything clearer

are you trying to bind to events in a browser?

Expand  

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:

  Reveal hidden contents
Posted
  On 9/22/2021 at 3:57 PM, 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.

 

Expand  

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:

  Reveal hidden contents
Posted (edited)

maybe you should look into using WebDriver UDF that is supported here for browser automation

that or UIAutomation

Edited by Earthshine

My resources are limited. You must ask the right questions

 

Posted

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.

Posted

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

 

 

 

Posted

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

Posted
  On 9/22/2021 at 7: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.

Expand  

I will take a look onto this, thank you!

  On 9/24/2021 at 12:03 AM, 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

 

 

 

Expand  

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:

  Reveal hidden contents
  • Melba23 changed the title to Convert GetRef function from VBScript to AutoIt
Posted

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

Posted (edited)

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 * IE on Windows 11 * How to ask ChatGPT for AutoIt Codefor other useful stuff click the following button:

  Reveal hidden contents

Signature last update: 2023-04-24

Posted (edited)

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

Expand  

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 * IE on Windows 11 * How to ask ChatGPT for AutoIt Codefor other useful stuff click the following button:

  Reveal hidden contents

Signature last update: 2023-04-24

Posted (edited)
  On 9/27/2021 at 1:31 PM, 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

Expand  

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

 

  On 9/27/2021 at 1:37 PM, 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
 

Expand  

@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:

  Reveal hidden contents

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