Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate

COM WinHttpRequest ResponseStream


  • Please log in to reply
18 replies to this topic
  • Guests
  • Last active:
  • Joined: --
Can somebody translate this code into AHK? The original web page seems to be closed. <!-- m -->http://www.jose.it-b... ... pic=2244.0<!-- m --> The credit goes to José Roca. Thanks.
' ========================================================================================
' The following example shows how to open an HTTP connection, send an HTTP request, and
' read the response as an IStream. The data from the IStream is written to a file.
' ========================================================================================

#COMPILE EXE
#DIM ALL
#DEBUG ERROR ON
#INCLUDE "httprequest.inc"
#INCLUDE "ole2utils.inc"

' ========================================================================================
' Main
' ========================================================================================
FUNCTION PBMAIN

   LOCAL pWHttp AS IWinHttpRequest
   LOCAL vSTream AS VARIANT
   LOCAL pIStream AS IStream
   LOCAL tstatstg AS STATSTG
   LOCAL strBuffer AS STRING
   LOCAL cb AS DWORD
   LOCAL cbRead AS DWORD
   LOCAL iSucceeded AS INTEGER

   ' Creates an instance of the HTTP service
   pWHttp = NEWCOM "WinHttp.WinHttpRequest.5.1"
   IF ISNOTHING(pWHttp) THEN EXIT FUNCTION

   TRY
      ' Opens an HTTP connection to an HTTP resource
      pWHttp.Open UCODE$("GET"), UCODE$("http://www.microsoft.com/library/homepage/images/ms-banner.gif")
      ' Sends an HTTP request to the HTTP server
      pWHttp.Send
      ' Wait for response with a timeout of 5 seconds
      iSucceeded = pWHttp.WaitForResponse(5)
      ' Get the response as a stream
      vStream = pWHttp.ResponseStream
      IF VARIANTVT(vStream) = %VT_UNKNOWN THEN
         pIStream = vStream
         vStream = EMPTY
         ' Get the size of the stream
         pIStream.Stat(tstatstg, %STATFLAG_NONAME)
         ' Use a string as a buffer
         strBuffer = SPACE$(tstatstg.cbsize)
         ' Read the stream
         pIStream.Read STRPTR(strBuffer), LEN(strBuffer), cbRead
         IF cbRead < tstatstg.cbsize THEN strBuffer = LEFT$(strBuffer, cbRead)
         pIStream = NOTHING
         ' Save the buffer into a file
         OPEN "ms-banner.gif" FOR BINARY AS #1
         PUT #1, 1, strBuffer
         CLOSE #1
         MSGBOX "File saved"
      END IF
   CATCH
      OleShowErrorInfo OBJRESULT
   END TRY

END FUNCTION
' ========================================================================================


jethrow
  • Moderators
  • 2854 posts
  • Last active: May 17 2017 01:57 AM
  • Joined: 24 May 2009
Well, here's the documentation for the WinHttpRequestObject. I'm interested to see what all you've tried so far ...

  • Guests
  • Last active:
  • Joined: --
I cannot figure out the part to get the stream and save it to a file.
pWHttp := ComObjCreate("WinHttp.WinHttpRequest.5.1")
	pWHttp.Open("GET", url, False) 				
	pWHttp.Send() 
	pWHttp.WaitForResponse(5)
	vStream := pWHttp.ResponseStream
	
	VT_UNKNOWN = 0xD

	if (ComObjType(vStream) = VT_UNKNOWN) {
		pIStream := vStream, vStream := ""
		
/*	No ideas what to do from here
		;Get the size of the stream
		;	pIStream.Stat(tstatstg, %STATFLAG_NONAME)
		;Use a string as a buffer
        ;	strBuffer = SPACE$(tstatstg.cbsize)	 
        ;Read the stream
        ;	pIStream.Read STRPTR(strBuffer), LEN(strBuffer), cbRead

		;IF cbRead < tstatstg.cbsize THEN strBuffer = LEFT$(strBuffer, cbRead)
        ;pIStream := ""
		
        ;Save the buffer into a file
        ; OPEN "ms-banner.gif" FOR BINARY AS #1
        ; PUT #1, 1, strBuffer
        ; CLOSE #1
*/
		msgbox File saved
	}


  • Guests
  • Last active:
  • Joined: --
OK, to save data, maybe we can use ADODB.Stream. But I don't know how to get and read streams.
pWHttp := ComObjCreate("WinHttp.WinHttpRequest.5.1")
	pWHttp.Open("GET", url, False) 				
	pWHttp.Send() 
	pWHttp.WaitForResponse(5)
	vStream := pWHttp.ResponseStream
	
	if (ComObjType(vStream) = 0xD) {		;VT_UNKNOWN = 0xD
		pIStream := vStream, vStream := ""
		
/*	No ideas what to do here
		;Get the size of the stream
		;	pIStream.Stat(tstatstg, %STATFLAG_NONAME)
		;Use a string as a buffer
        ;	strBuffer = SPACE$(tstatstg.cbsize)	 
        ;Read the stream
        ;	pIStream.Read STRPTR(strBuffer), LEN(strBuffer), cbRead

		;IF cbRead < tstatstg.cbsize THEN strBuffer = LEFT$(strBuffer, cbRead)
*/		
        pIStream := ""
        ;Save the buffer into a file
		pstm := ComObjCreate("ADODB.Stream")	
		pstm.Type() := 1		;Binary File : 1, Text File : 2 
		pstm.Open()		
		pstm.Write(strBuffer)
		pstm.SaveToFile(A_ScriptDir "\ms-banner.gif", overwrite ? 2 : 1)
		pstm.Close() 
		pstm := ""		

		msgbox File saved
	}


  • Guests
  • Last active:
  • Joined: --
In case someone is interested in to figure it out, the above code use the IStream.Stat method and Read method.

  • Guests
  • Last active:
  • Joined: --
It seems the Stat method requires the STATSTG structure and I'm afraid that AHK does not support it.

jethrow
  • Moderators
  • 2854 posts
  • Last active: May 17 2017 01:57 AM
  • Joined: 24 May 2009
<!-- m -->https://ahknet.autoh... ... htm#struct<!-- m -->

  • Guests
  • Last active:
  • Joined: --
mind writing a working example :?:

jethrow
  • Moderators
  • 2854 posts
  • Last active: May 17 2017 01:57 AM
  • Joined: 24 May 2009

mind writing a working example :?:

:lol: - I would have already if I knew how. I was stuck at the IUnknown Interface pointer ...

  • Guests
  • Last active:
  • Joined: --
Bump :D

maul.esel
  • Members
  • 790 posts
  • Last active: Jan 05 2013 09:26 PM
  • Joined: 28 Feb 2011
Damn, this is ugly. WinHttpRequest.ResponseStream seems to be an object (IsObject(vStream) returns true), but not an IDispatch (vStream.Stat(...) fires an error).
So I didn't succeed in getting the pointer, too. :?

What I did so far: (not working)
/*' ========================================================================================
' The following example shows how to open an HTTP connection, send an HTTP request, and
' read the response as an IStream. The data from the IStream is written to a file.
' ========================================================================================

#COMPILE EXE
#DIM ALL
#DEBUG ERROR ON
#INCLUDE "httprequest.inc"
#INCLUDE "ole2utils.inc"

' ========================================================================================
' Main
' ========================================================================================
FUNCTION PBMAIN

   LOCAL pWHttp AS IWinHttpRequest
   LOCAL vStream AS VARIANT
   LOCAL pIStream AS IStream
   LOCAL tstatstg AS STATSTG
   LOCAL strBuffer AS STRING
   LOCAL cb AS DWORD
   LOCAL cbRead AS DWORD
   LOCAL iSucceeded AS INTEGER
*/
/*
   ' Creates an instance of the HTTP service
   pWHttp = NEWCOM "WinHttp.WinHttpRequest.5.1"
   IF ISNOTHING(pWHttp) THEN EXIT FUNCTION
*/
pWHttp := ComObjCreate("WinHttp.WinHttpRequest.5.1")
;pWHttp := ComObjCreate("{2087c2f4-2cef-4953-a8ab-66779b670495}", "{016fe2ec-b2c8-45f8-b23b-39e53a75396b}")

/*
TRY
*/
	/*
	' Opens an HTTP connection to an HTTP resource
	pWHttp.Open UCODE$("GET"), UCODE$("http://www.microsoft.com/library/homepage/images/ms-banner.gif")
	*/
	pWHttp.Open("GET", "http://www.microsoft.com/library/homepage/images/ms-banner.gif", true)
	
	/*
	' Sends an HTTP request to the HTTP server
	pWHttp.Send
	*/
	pWHttp.Send()
	
	/*
	' Wait for response with a timeout of 5 seconds
	iSucceeded = pWHttp.WaitForResponse(5)
	*/
	iSucceeded := pWHttp.WaitForResponse()
	
	/*
	' Get the response as a stream
	vStream = pWHttp.ResponseStream
	*/
	vStream := pWHttp.ResponseStream
	
	/*
	IF VARIANTVT(vStream) = %VT_UNKNOWN THEN
	*/
	VT_UNKNOWN = 0xD
	if (ComObjType(vStream) = VT_UNKNOWN) {
		/*
		pIStream = vStream
        vStream = EMPTY
		*/
		pIStream := vStream, vStream := ""
		
		/*
		' Get the size of the stream
         pIStream.Stat(tstatstg, %STATFLAG_NONAME)
		*/
		STATFLAG_NONAME := 1
		VarSetCapacity(tstatstg, 60 + A_PtrSize, 0)
		DllCall(NumGet(NumGet(pIStream + 0) + 12 * A_PtrSize), "ptr", pIStream, "ptr", &tstatstg, "uint", STATFLAG_NONAME) ; Stat()
		
		/*
		' Use a string as a buffer
         strBuffer = SPACE$(tstatstg.cbsize)
		*/
		tstatstg_cbsize := NumGet(tstatstg, A_PtrSize + 4, "uint")
		VarSetCapacity(strBuffer, tstatstg_cbsize)
		
		/*
		' Read the stream
         pIStream.Read STRPTR(strBuffer), LEN(strBuffer), cbRead
		*/
		 DllCall(NumGet(NumGet(pIStream + 0) + 3 * A_PtrSize), "ptr", pIStream, "ptr", &strBuffer, "uint", tstatstg_cbsize, "uint*", cbRead)
		
		/*
		IF cbRead < tstatstg.cbsize THEN strBuffer = LEFT$(strBuffer, cbRead)
		*/
		if (cbRead < tstatstg_cbsize)
		{
			tstatstg_cbsize := cbRead ; not use if correct / didn't find a better way
		}
		
		/*
		pIStream = NOTHING
		*/
		VarSetCapacity(pIStream, 0)
		
		/*
		' Save the buffer into a file
         OPEN "ms-banner.gif" FOR BINARY AS #1
         PUT #1, 1, strBuffer
         CLOSE #1
		*/
		file := FileOpen("ms-banner.gif", "w")
		file.RawWrite(&strBuffer, tstatstg_cbsize)
		file.Close()
		
		/*
		MSGBOX "File saved"
		*/
		msgbox File saved
		Run ms-banner.gif
	/*
	END IF
	*/
	}
	  /*
   CATCH
      OleShowErrorInfo OBJRESULT
   END TRY

END FUNCTION
' ========================================================================================
*/
It may be possible to do this by avoiding objects at all and only working with the pointers.
Join the discussion on The future of AutoHotkey
Posted Image Visit me on github Posted Image
Win7 HP SP1 64bit | AHK_L U 64bit

sinkfaze
  • Moderators
  • 6367 posts
  • Last active: Nov 30 2018 08:50 PM
  • Joined: 18 Mar 2008

WinHttpRequest.ResponseStream seems to be an object (IsObject(vStream) returns true), but not an IDispatch...


It's IStream.

For AHK you might rather use ResponseText.

maul.esel
  • Members
  • 790 posts
  • Last active: Jan 05 2013 09:26 PM
  • Joined: 28 Feb 2011
I know it's IStream :roll:, but it seems to be an AHK object (instead of only an interface pointer).

I thought of using ResponseBody instead, because (at least in the example above) we're dealing with an image. I didn't manage to get it's length (for file.RawWrite(VarOderAdresse, Bytes)).
Join the discussion on The future of AutoHotkey
Posted Image Visit me on github Posted Image
Win7 HP SP1 64bit | AHK_L U 64bit

sinkfaze
  • Moderators
  • 6367 posts
  • Last active: Nov 30 2018 08:50 PM
  • Joined: 18 Mar 2008

...but it seems to be an AHK object (instead of only an interface pointer).


Why would it be an interface pointer? Seems to me it should be a wrapper object.

maul.esel
  • Members
  • 790 posts
  • Last active: Jan 05 2013 09:26 PM
  • Joined: 28 Feb 2011

Why would it be an interface pointer?

I expected only IDispatchs to be wrapped. Also, from dealing with other non-Dispatch interfaces in COM Classes Project, I'm used to getting an interface pointer.
Join the discussion on The future of AutoHotkey
Posted Image Visit me on github Posted Image
Win7 HP SP1 64bit | AHK_L U 64bit