Jump to content

WinHTTP functions


trancexx
 Share

Recommended Posts

Can you give me the exact code? I can't make it crash here (win 7 x64) no matter what I do.

What system are you running the script on?

I tried this script with dozens calls every 1sec at different server with no crash at all.

WinXP SP2, all working well, here.

Example code:

#include "WinHttp.au3"

;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
; Reserve memory space for asynchronous work
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
; The size
Global Const $iSizeBufferAsync = 1048576 ; 1MB for example, should be  enough
; The buffer
Global Static $tBufferAsync = DllStructCreate("byte[" & $iSizeBufferAsync & "]")
; Get pointer to this memory space
Global $pBufferAsync = DllStructGetPtr($tBufferAsync)

php("google.com", "")
Sleep(1000)
php("msdn.microsoft.com","en-us/library/aa383917(v=vs.85).aspx")
Sleep(1000)
exit


func php($server,$url)

; Register Callback function
Global $hWINHTTP_STATUS_CALLBACK = DllCallbackRegister("__WINHTTP_STATUS_CALLBACK", "none", "handle;dword_ptr;dword;ptr;dword")

; Initialize and get session handle. Asynchronous flag.
Global $hOpen = _WinHttpOpen(Default, Default, Default, Default, $WINHTTP_FLAG_ASYNC)

; Assign callback function
_WinHttpSetStatusCallback($hOpen, $hWINHTTP_STATUS_CALLBACK)

; Get connection handle
Global $hConnect = _WinHttpConnect($hOpen, $server)

; Make request
Global $hRequest = _WinHttpOpenRequest($hConnect, Default, $url)

; Send it
_WinHttpSendRequest($hRequest)

; Some dummy code for waiting
Sleep(2000)

; Close handles
_WinHttpCloseHandle($hRequest)
_WinHttpCloseHandle($hConnect)
_WinHttpCloseHandle($hOpen)
; Free callback. Redundant here
DllCallbackFree($hWINHTTP_STATUS_CALLBACK)

EndFunc ;php

;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
; Define callback function
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Func __WINHTTP_STATUS_CALLBACK($hInternet, $iContext, $iInternetStatus, $pStatusInformation, $iStatusInformationLength)
    #forceref $hInternet, $iContext, $pStatusInformation, $iStatusInformationLength
    ConsoleWrite(">> ")
    ; Interpret the status
    Local $sStatus
    Switch $iInternetStatus
        Case $WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION
            $sStatus = "Closing the connection to the server"
        Case $WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER
            $sStatus = "Successfully connected to the server."
        Case $WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER
            $sStatus = "Connecting to the server."
        Case $WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED
            $sStatus = "Successfully closed the connection to the server."
        Case $WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE
            $sStatus = "Data is available to be retrieved with WinHttpReadData."
            ConsoleWrite($sStatus & @CRLF)

            ;*************************************
            ; Read asynchronously
            ;*************************************
            _WinHttpSimpleReadDataAsync($hInternet, $pBufferAsync, $iSizeBufferAsync)
            Return

        Case $WINHTTP_CALLBACK_STATUS_HANDLE_CREATED
            $sStatus = "An HINTERNET handle has been created: " & $hInternet
        Case $WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
            $sStatus = "This handle value has been terminated: " & $hInternet
        Case $WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE
            $sStatus = "The response header has been received and is available with WinHttpQueryHeaders."
            ConsoleWrite($sStatus & @CRLF)

            ;*************************************
            ; Print header
            ;*************************************
            ConsoleWrite(_WinHttpQueryHeaders($hInternet) & @CRLF)

            ;*************************************
            ; Check if there is any data available
            ;*************************************
            _WinHttpQueryDataAvailable($hInternet)

            Return

        Case $WINHTTP_CALLBACK_STATUS_INTERMEDIATE_RESPONSE
            $sStatus = "Received an intermediate (100 level) status code message from the server."
        Case $WINHTTP_CALLBACK_STATUS_NAME_RESOLVED
            $sStatus = "Successfully found the IP address of the server."
        Case $WINHTTP_CALLBACK_STATUS_READ_COMPLETE
            $sStatus = "Data was successfully read from the server."
            ConsoleWrite($sStatus & @CRLF)

            ;*************************************
            ; Print read data
            ;*************************************
            Local $sRead = DllStructGetData(DllStructCreate("char[" & $iStatusInformationLength & "]", $pStatusInformation), 1)
            ConsoleWrite($sRead & @CRLF)

            Return

        Case $WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE
            $sStatus = "Waiting for the server to respond to a request."
        Case $WINHTTP_CALLBACK_STATUS_REDIRECT
            $sStatus = "An HTTP request is about to automatically redirect the request."
        Case $WINHTTP_CALLBACK_STATUS_REQUEST_ERROR
            $sStatus = "An error occurred while sending an HTTP request."
        Case $WINHTTP_CALLBACK_STATUS_REQUEST_SENT
            $sStatus = "Successfully sent the information request to the server."
        Case $WINHTTP_CALLBACK_STATUS_RESOLVING_NAME
            $sStatus = "Looking up the IP address of a server name."
        Case $WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED
            $sStatus = "Successfully received a response from the server."
        Case $WINHTTP_CALLBACK_STATUS_SECURE_FAILURE
            $sStatus = "One or more errors were encountered while retrieving a Secure Sockets Layer (SSL) certificate from the server."
        Case $WINHTTP_CALLBACK_STATUS_SENDING_REQUEST
            $sStatus = "Sending the information request to the server."
        Case $WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE
            $sStatus = "The request completed successfully."
            ConsoleWrite($sStatus & @CRLF)

            ;*************************************
            ; Receive Response
            ;*************************************
            _WinHttpReceiveResponse($hInternet)
            Return

        Case $WINHTTP_CALLBACK_STATUS_WRITE_COMPLETE
            $sStatus = "Data was successfully written to the server."
    EndSwitch
    ; Print it
    ConsoleWrite($sStatus & @CRLF)
EndFunc ;==>__WINHTTP_STATUS_CALLBACK
Edited by frank10
Link to comment
Share on other sites

Ok, I found a crash... but I don't know why, repeating the exact code worked well..

Another problem is If one call to a server and it doesn't respond immediately, you put the msgbox after the sendRequest, but in a real script how can you wait asyncronously for the server's answer?

If you put a Do... until linked to some @error or other check, you block the script and it's no more async.

If you put a generic sleep, you can't fit the exact server time and if you put a sleep too short the connection close and the server's echo doesn't get anymore...

So it seems it's not real async.

Link to comment
Share on other sites

It is strange. Currently I cannot reproduce the error no matter what I do. I only get it to crash if I use _WinHttpReceiveResponse outside of __WINHTTP_STATUS_CALLBACK now.

AutoIt:3.3.6.1 X64, AutoIt:3.3.6.1 X86, AutoIt:3.3.7.8/X64 AutoIt:3.3.7.8/X86 (Os:WIN_7/SP1/X64 OSLang:0407)

This was the script:

#AutoIt3Wrapper_AU3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6

#include "WinHttp.au3"
#include "Debug.au3"
ConsoleWrite( _DebugBugReportEnv( ) & @CRLF)

Opt("MustDeclareVars", 1)

;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
; Reserve memory space for asynchronous work
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
; The size
Global Const $iSizeBufferAsync = 1048576 ; 1MB for example, should be enough
; The buffer
Global Static $tBufferAsync = DllStructCreate("byte[" & $iSizeBufferAsync & "]")
; Get pointer to this memory space
Global $pBufferAsync = DllStructGetPtr($tBufferAsync)



; Register Callback function
Global $hWINHTTP_STATUS_CALLBACK = DllCallbackRegister("__WINHTTP_STATUS_CALLBACK", "none", "handle;dword_ptr;dword;ptr;dword")

; Initialize and get session handle. Asynchronous flag.
Global $hOpen = _WinHttpOpen(Default, Default, Default, Default, $WINHTTP_FLAG_ASYNC)

; Assign callback function
_WinHttpSetStatusCallback($hOpen, $hWINHTTP_STATUS_CALLBACK)

; Get connection handle
Global $hConnect = _WinHttpConnect($hOpen, "msdn.microsoft.com")

; Make request
Global $hRequest = _WinHttpOpenRequest($hConnect, Default, "en-us/library/aa383917(v=vs.85).aspx")

; Send it
_WinHttpSendRequest($hRequest)

; Some dummy code for waiting
MsgBox(64 + 262144, "Wait...", "Wait for the results if they are not shown already.")


; Close handles
_WinHttpCloseHandle($hRequest)
_WinHttpCloseHandle($hConnect)
_WinHttpCloseHandle($hOpen)
; Free callback. Redundant here
DllCallbackFree($hWINHTTP_STATUS_CALLBACK)



;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
; Define callback function
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Func __WINHTTP_STATUS_CALLBACK($hInternet, $iContext, $iInternetStatus, $pStatusInformation, $iStatusInformationLength)
    #forceref $hInternet, $iContext, $pStatusInformation, $iStatusInformationLength
    ConsoleWrite(">> ")
    ; Interpret the status
    Local $sStatus
    Switch $iInternetStatus
        Case $WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION
            $sStatus = "Closing the connection to the server"
        Case $WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER
            $sStatus = "Successfully connected to the server."
        Case $WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER
            $sStatus = "Connecting to the server."
        Case $WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED
            $sStatus = "Successfully closed the connection to the server."
        Case $WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE
            $sStatus = "Data is available to be retrieved with WinHttpReadData."
        Case $WINHTTP_CALLBACK_STATUS_HANDLE_CREATED
            $sStatus = "An HINTERNET handle has been created: " & $hInternet
        Case $WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
            $sStatus = "This handle value has been terminated: " & $hInternet
        Case $WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE
            $sStatus = "The response header has been received and is available with WinHttpQueryHeaders."
        Case $WINHTTP_CALLBACK_STATUS_INTERMEDIATE_RESPONSE
            $sStatus = "Received an intermediate (100 level) status code message from the server."
        Case $WINHTTP_CALLBACK_STATUS_NAME_RESOLVED
            $sStatus = "Successfully found the IP address of the server."
        Case $WINHTTP_CALLBACK_STATUS_READ_COMPLETE
            $sStatus = "Data was successfully read from the server."
        Case $WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE
            $sStatus = "Waiting for the server to respond to a request."
        Case $WINHTTP_CALLBACK_STATUS_REDIRECT
            $sStatus = "An HTTP request is about to automatically redirect the request."
        Case $WINHTTP_CALLBACK_STATUS_REQUEST_ERROR
            $sStatus = "An error occurred while sending an HTTP request."
        Case $WINHTTP_CALLBACK_STATUS_REQUEST_SENT
            $sStatus = "Successfully sent the information request to the server."
        Case $WINHTTP_CALLBACK_STATUS_RESOLVING_NAME
            $sStatus = "Looking up the IP address of a server name."
        Case $WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED
            $sStatus = "Successfully received a response from the server."
        Case $WINHTTP_CALLBACK_STATUS_SECURE_FAILURE
            $sStatus = "One or more errors were encountered while retrieving a Secure Sockets Layer (SSL) certificate from the server."
        Case $WINHTTP_CALLBACK_STATUS_SENDING_REQUEST
            $sStatus = "Sending the information request to the server."
        Case $WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE
            $sStatus = "The request completed successfully."
        Case $WINHTTP_CALLBACK_STATUS_WRITE_COMPLETE
            $sStatus = "Data was successfully written to the server."
    EndSwitch
    ; Print it
    ConsoleWrite($sStatus & @CRLF)
EndFunc    ;==>__WINHTTP_STATUS_CALLBACK

Edit: This is a game of luck. I added _WinHttpQueryDataAvailable($hInternet) to $WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE and _WinHttpReceiveResponse($hInternet) to $WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE. Now I got some crashes again. (AutoIt simply exits with exitcode 1 or "Variable not declared" or a windows crash message.) It just depends on when the callback is actially called I think.

Edited by ProgAndy

*GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

Link to comment
Share on other sites

I don't think you should be testing with a blocking function like MsgBox. It would be safer to use a while - sleep - wend loop that checks for a global flag to exit the loop. It's kinda like the warning AutoIt has about using blocking functions inside a GuiRegisterMsg callback.

Link to comment
Share on other sites

Another problem is If one call to a server and it doesn't respond immediately, you put the msgbox after the sendRequest, but in a real script how can you wait asyncronously for the server's answer?

If you put a Do... until linked to some @error or other check, you block the script and it's no more async.

That's not true. AutoIt can do whatever it wants during Sleep(), it is not considered a 'blocking' function like MsgBox. So a while - sleep - wend loop with a global exit flag is perfect for async and callbacks. You just have to know when to set the loop's exit flag from the callback.

Link to comment
Share on other sites

Asynchronous WinHttp has to be able to execute multiple requests at the same time. Here is an example that is crashing each time I execute it.

#AutoIt3Wrapper_AU3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6

#include "WinHttp.au3"
#include "Debug.au3"
ConsoleWrite( _DebugBugReportEnv( ) & @CRLF)

Opt("MustDeclareVars", 1)


; Register Callback function
Global $hWINHTTP_STATUS_CALLBACK = DllCallbackRegister("__WINHTTP_STATUS_CALLBACK", "none", "handle;dword_ptr;dword;ptr;dword")

; Initialize and get session handle. Asynchronous flag.
Global $hOpen = _WinHttpOpen(Default, Default, Default, Default, $WINHTTP_FLAG_ASYNC)

; Assign callback function
_WinHttpSetStatusCallback($hOpen, $hWINHTTP_STATUS_CALLBACK)
Global $EXIT = 0
Global $hConnect[10], $hRequest[10]
Global $aSites[10] = ["google.de", "autoitscript.com", "autoit.de", "msdn.microsoft.com", "google.com", "live.com", "web.de", "aol.com", "miranda-im.org", "dropbox.com"]
For $i = 0 To 9
; Get connection handle
$hConnect[$i] = _WinHttpConnect($hOpen, $aSites[$i])

; Make request
$hRequest[$i] = _WinHttpOpenRequest($hConnect[$i], Default, "/")

; Send it
_WinHttpSendRequest($hRequest[$i])

Next

Do
    Sleep(20)
Until $EXIT = 10

; Close handles
For $i = 0 To 9
_WinHttpCloseHandle($hRequest[$i])
_WinHttpCloseHandle($hConnect[$i])
Next
_WinHttpCloseHandle($hOpen)
; Free callback. Redundant here
DllCallbackFree($hWINHTTP_STATUS_CALLBACK)



;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
; Define callback function
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Func __WINHTTP_STATUS_CALLBACK($hInternet, $iContext, $iInternetStatus, $pStatusInformation, $iStatusInformationLength)
    #forceref $hInternet, $iContext, $pStatusInformation, $iStatusInformationLength
    ConsoleWrite(">> ")
    ; Interpret the status
    Local $sStatus
    Switch $iInternetStatus
        Case $WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION
            $sStatus = "Closing the connection to the server"
        Case $WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER
            $sStatus = "Successfully connected to the server."
        Case $WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER
            $sStatus = "Connecting to the server."
        Case $WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED
            $sStatus = "Successfully closed the connection to the server."
        Case $WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE
            $sStatus = "Data is available to be retrieved with WinHttpReadData."
        Case $WINHTTP_CALLBACK_STATUS_HANDLE_CREATED
            $sStatus = "An HINTERNET handle has been created: " & $hInternet
        Case $WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
            $sStatus = "This handle value has been terminated: " & $hInternet
        Case $WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE
            $sStatus = "The response header has been received and is available with WinHttpQueryHeaders."
            _WinHttpQueryDataAvailable($hInternet)
            $EXIT += 1
        Case $WINHTTP_CALLBACK_STATUS_INTERMEDIATE_RESPONSE
            $sStatus = "Received an intermediate (100 level) status code message from the server."
        Case $WINHTTP_CALLBACK_STATUS_NAME_RESOLVED
            $sStatus = "Successfully found the IP address of the server."
        Case $WINHTTP_CALLBACK_STATUS_READ_COMPLETE
            $sStatus = "Data was successfully read from the server."
        Case $WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE
            $sStatus = "Waiting for the server to respond to a request."
        Case $WINHTTP_CALLBACK_STATUS_REDIRECT
            $sStatus = "An HTTP request is about to automatically redirect the request."
        Case $WINHTTP_CALLBACK_STATUS_REQUEST_ERROR
            $sStatus = "An error occurred while sending an HTTP request."
        Case $WINHTTP_CALLBACK_STATUS_REQUEST_SENT
            $sStatus = "Successfully sent the information request to the server."
        Case $WINHTTP_CALLBACK_STATUS_RESOLVING_NAME
            $sStatus = "Looking up the IP address of a server name."
        Case $WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED
            $sStatus = "Successfully received a response from the server."
        Case $WINHTTP_CALLBACK_STATUS_SECURE_FAILURE
            $sStatus = "One or more errors were encountered while retrieving a Secure Sockets Layer (SSL) certificate from the server."
        Case $WINHTTP_CALLBACK_STATUS_SENDING_REQUEST
            $sStatus = "Sending the information request to the server."
        Case $WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE
            $sStatus = "The request completed successfully."
            _WinHttpReceiveResponse($hInternet)
        Case $WINHTTP_CALLBACK_STATUS_WRITE_COMPLETE
            $sStatus = "Data was successfully written to the server."
    EndSwitch
    ; Print it
    ConsoleWrite($sStatus & @CRLF)
EndFunc    ;==>__WINHTTP_STATUS_CALLBACK

*GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

Link to comment
Share on other sites

Well, yes but he has put MsgBox after the SendRequest, not into the callback func.

So if you make a Func to handle the http calls to the server and put some While-Sleep, you end up blocking the entire script.

He should put the While-sleep inside the callback func, so if it's fired several times can have some instances blocked by the while-sleep while the rest of script continues. I hope understanding how autoit uses callback func and sleep cycles...

But in the way he coded the async example, if you substitute a msgbox with a sleep you block the entire script.

Link to comment
Share on other sites

Asynchronous WinHttp has to be able to execute multiple requests at the same time. Here is an example that is crashing each time I execute it.

#AutoIt3Wrapper_AU3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6

#include "WinHttp.au3"
#include "Debug.au3"
ConsoleWrite( _DebugBugReportEnv( ) & @CRLF)

Opt("MustDeclareVars", 1)


; Register Callback function
Global $hWINHTTP_STATUS_CALLBACK = DllCallbackRegister("__WINHTTP_STATUS_CALLBACK", "none", "handle;dword_ptr;dword;ptr;dword")

; Initialize and get session handle. Asynchronous flag.
Global $hOpen = _WinHttpOpen(Default, Default, Default, Default, $WINHTTP_FLAG_ASYNC)

; Assign callback function
_WinHttpSetStatusCallback($hOpen, $hWINHTTP_STATUS_CALLBACK)
Global $EXIT = 0
Global $hConnect[10], $hRequest[10]
Global $aSites[10] = ["google.de", "autoitscript.com", "autoit.de", "msdn.microsoft.com", "google.com", "live.com", "web.de", "aol.com", "miranda-im.org", "dropbox.com"]
For $i = 0 To 9
; Get connection handle
$hConnect[$i] = _WinHttpConnect($hOpen, $aSites[$i])

; Make request
$hRequest[$i] = _WinHttpOpenRequest($hConnect[$i], Default, "/")

; Send it
_WinHttpSendRequest($hRequest[$i])

Next

Do
    Sleep(20)
Until $EXIT = 10

; Close handles
For $i = 0 To 9
_WinHttpCloseHandle($hRequest[$i])
_WinHttpCloseHandle($hConnect[$i])
Next
_WinHttpCloseHandle($hOpen)
; Free callback. Redundant here
DllCallbackFree($hWINHTTP_STATUS_CALLBACK)



;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
; Define callback function
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Func __WINHTTP_STATUS_CALLBACK($hInternet, $iContext, $iInternetStatus, $pStatusInformation, $iStatusInformationLength)
    #forceref $hInternet, $iContext, $pStatusInformation, $iStatusInformationLength
    ConsoleWrite(">> ")
    ; Interpret the status
    Local $sStatus
    Switch $iInternetStatus
        Case $WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION
            $sStatus = "Closing the connection to the server"
        Case $WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER
            $sStatus = "Successfully connected to the server."
        Case $WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER
            $sStatus = "Connecting to the server."
        Case $WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED
            $sStatus = "Successfully closed the connection to the server."
        Case $WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE
            $sStatus = "Data is available to be retrieved with WinHttpReadData."
        Case $WINHTTP_CALLBACK_STATUS_HANDLE_CREATED
            $sStatus = "An HINTERNET handle has been created: " & $hInternet
        Case $WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
            $sStatus = "This handle value has been terminated: " & $hInternet
        Case $WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE
            $sStatus = "The response header has been received and is available with WinHttpQueryHeaders."
            _WinHttpQueryDataAvailable($hInternet)
            $EXIT += 1
        Case $WINHTTP_CALLBACK_STATUS_INTERMEDIATE_RESPONSE
            $sStatus = "Received an intermediate (100 level) status code message from the server."
        Case $WINHTTP_CALLBACK_STATUS_NAME_RESOLVED
            $sStatus = "Successfully found the IP address of the server."
        Case $WINHTTP_CALLBACK_STATUS_READ_COMPLETE
            $sStatus = "Data was successfully read from the server."
        Case $WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE
            $sStatus = "Waiting for the server to respond to a request."
        Case $WINHTTP_CALLBACK_STATUS_REDIRECT
            $sStatus = "An HTTP request is about to automatically redirect the request."
        Case $WINHTTP_CALLBACK_STATUS_REQUEST_ERROR
            $sStatus = "An error occurred while sending an HTTP request."
        Case $WINHTTP_CALLBACK_STATUS_REQUEST_SENT
            $sStatus = "Successfully sent the information request to the server."
        Case $WINHTTP_CALLBACK_STATUS_RESOLVING_NAME
            $sStatus = "Looking up the IP address of a server name."
        Case $WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED
            $sStatus = "Successfully received a response from the server."
        Case $WINHTTP_CALLBACK_STATUS_SECURE_FAILURE
            $sStatus = "One or more errors were encountered while retrieving a Secure Sockets Layer (SSL) certificate from the server."
        Case $WINHTTP_CALLBACK_STATUS_SENDING_REQUEST
            $sStatus = "Sending the information request to the server."
        Case $WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE
            $sStatus = "The request completed successfully."
            _WinHttpReceiveResponse($hInternet)
        Case $WINHTTP_CALLBACK_STATUS_WRITE_COMPLETE
            $sStatus = "Data was successfully written to the server."
    EndSwitch
    ; Print it
    ConsoleWrite($sStatus & @CRLF)
EndFunc    ;==>__WINHTTP_STATUS_CALLBACK

In my pc your code ( copy & paste ) works every time.:huh2:

Link to comment
Share on other sites

ProgAndy is right of course. I'll add few notes to the help file for the next release.

Strangely, it just won't crash for me. I should play the lottery.

Just to clear one thing up... ProgAndy if you split the code to 10 sessions running at the same time and you set one callback for every session (the same callback function registered 10 times or just once), does it crash then?

Edited by trancexx
Link to comment
Share on other sites

I deleted the msgbox or the sleep after the SendRequest and moved the closeHandles into the callback func after the print data:

Case $WINHTTP_CALLBACK_STATUS_READ_COMPLETE
            $sStatus = "Data was successfully read from the server."
            ConsoleWrite($sStatus & @CRLF)

            ;*************************************
            ; Print read data
            ;*************************************
            Local $sRead = DllStructGetData(DllStructCreate("char[" & $iStatusInformationLength & "]", $pStatusInformation), 1)
            ConsoleWrite($sRead & @CRLF)

            _WinHttpCloseHandle($hRequest)
            _WinHttpCloseHandle($hConnect)
            _WinHttpCloseHandle($hOpen)

the rest of code is like my previous

This way it automatically waits from the server and only when it gots all, closes handles.

This works also with multi calls that 'overlaps' themselves: if one call hasn't finished its job, you can continue calling other urls, and when the old data arrives it works well.

I found consistent crash if I add

DllCallbackFree($hWINHTTP_STATUS_CALLBACK)

after closing handles in the callback func.

Anyway it doesn't seem to be necessary...

EDIT: CallbackFree shouldn't be used when some handles are still alive, so it should be checked when the last handle closes, then use DllCallBackFree...

BUT, even with one unique call, after closing all handles, it crashes if called from Callback func.

Edited by frank10
Link to comment
Share on other sites

Just to clear one thing up... ProgAndy if you split the code to 10 sessions running at the same time and you set one callback for every session (the same callback function registered 10 times or just once), does it crash then?

It still crashes:

#AutoIt3Wrapper_AU3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6

#include "WinHttp.au3"
#include "Debug.au3"
ConsoleWrite( _DebugBugReportEnv( ) & @CRLF)

Opt("MustDeclareVars", 1)

Global Const $count = 10 ; How many pages shall be opened (10 is maximum)
Global $EXIT = 0
Global $hConnect[10], $hRequest[10]
Global $hWINHTTP_STATUS_CALLBACK[10], $hOpen[10]
For $i = 0 To $count-1

; Register Callback function
$hWINHTTP_STATUS_CALLBACK[$i] = DllCallbackRegister("__WINHTTP_STATUS_CALLBACK", "none", "handle;dword_ptr;dword;ptr;dword")

; Initialize and get session handle. Asynchronous flag.
$hOpen[$i] = _WinHttpOpen(Default, Default, Default, Default, $WINHTTP_FLAG_ASYNC)

; Assign callback function
_WinHttpSetStatusCallback($hOpen[$i], $hWINHTTP_STATUS_CALLBACK[$i])

Global $aSites[10] = ["google.de", "autoitscript.com", "autoit.de", "msdn.microsoft.com", "google.com", "live.com", "web.de", "aol.com", "miranda-im.org", "dropbox.com"]

; Get connection handle
$hConnect[$i] = _WinHttpConnect($hOpen[$i], $aSites[$i])

; Make request
$hRequest[$i] = _WinHttpOpenRequest($hConnect[$i], Default, "/")

; Send it
_WinHttpSendRequest($hRequest[$i])

Next

Do
    Sleep(20)
Until $EXIT = $count

; Close handles
For $i = 0 To 9
_WinHttpCloseHandle($hRequest[$i])
_WinHttpCloseHandle($hConnect[$i])
_WinHttpCloseHandle($hOpen[$i])
; Free callback. Redundant here
DllCallbackFree($hWINHTTP_STATUS_CALLBACK[$i])
Next



;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
; Define callback function
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Func __WINHTTP_STATUS_CALLBACK($hInternet, $iContext, $iInternetStatus, $pStatusInformation, $iStatusInformationLength)
    #forceref $hInternet, $iContext, $pStatusInformation, $iStatusInformationLength
    ConsoleWrite(">> ")
    ; Interpret the status
    Local $sStatus
    Switch $iInternetStatus
        Case $WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION
            $sStatus = "Closing the connection to the server"
        Case $WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER
            $sStatus = "Successfully connected to the server."
        Case $WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER
            $sStatus = "Connecting to the server."
        Case $WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED
            $sStatus = "Successfully closed the connection to the server."
        Case $WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE
            $sStatus = "Data is available to be retrieved with WinHttpReadData."
        Case $WINHTTP_CALLBACK_STATUS_HANDLE_CREATED
            $sStatus = "An HINTERNET handle has been created: " & $hInternet
        Case $WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
            $sStatus = "This handle value has been terminated: " & $hInternet
        Case $WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE
            $sStatus = "The response header has been received and is available with WinHttpQueryHeaders."
            _WinHttpQueryDataAvailable($hInternet)
            $EXIT += 1
        Case $WINHTTP_CALLBACK_STATUS_INTERMEDIATE_RESPONSE
            $sStatus = "Received an intermediate (100 level) status code message from the server."
        Case $WINHTTP_CALLBACK_STATUS_NAME_RESOLVED
            $sStatus = "Successfully found the IP address of the server."
        Case $WINHTTP_CALLBACK_STATUS_READ_COMPLETE
            $sStatus = "Data was successfully read from the server."
        Case $WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE
            $sStatus = "Waiting for the server to respond to a request."
        Case $WINHTTP_CALLBACK_STATUS_REDIRECT
            $sStatus = "An HTTP request is about to automatically redirect the request."
        Case $WINHTTP_CALLBACK_STATUS_REQUEST_ERROR
            $sStatus = "An error occurred while sending an HTTP request."
        Case $WINHTTP_CALLBACK_STATUS_REQUEST_SENT
            $sStatus = "Successfully sent the information request to the server."
        Case $WINHTTP_CALLBACK_STATUS_RESOLVING_NAME
            $sStatus = "Looking up the IP address of a server name."
        Case $WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED
            $sStatus = "Successfully received a response from the server."
        Case $WINHTTP_CALLBACK_STATUS_SECURE_FAILURE
            $sStatus = "One or more errors were encountered while retrieving a Secure Sockets Layer (SSL) certificate from the server."
        Case $WINHTTP_CALLBACK_STATUS_SENDING_REQUEST
            $sStatus = "Sending the information request to the server."
        Case $WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE
            $sStatus = "The request completed successfully."
            _WinHttpReceiveResponse($hInternet)
        Case $WINHTTP_CALLBACK_STATUS_WRITE_COMPLETE
            $sStatus = "Data was successfully written to the server."
    EndSwitch
    ; Print it
    ConsoleWrite($sStatus & @CRLF)
EndFunc    ;==>__WINHTTP_STATUS_CALLBACK

AutoIt:3.3.6.1/X64   (Os:WIN_7/X64/Service Pack 1   Language:0407 Keyboard:00000407 Cpu:X64)

D:\Dokumente\AutoIt3\UDF\WinHttp.au3 (795) : ==> Subscript used with non-Array variable.:
If @error Or Not $aCall[0] Then Return SetError(1, 0, 0)
If @error Or Not $aCall^ ERROR
...
D:\Dokumente\AutoIt3\winhttptest.au3 (59) : ==> Variable used without being declared.:
Switch $iInternetStatus
Switch ^ ERROR

Similar errors with beta and in x86 mode. Sometimes even a Windows crash dialog.

Edited by ProgAndy

*GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

Link to comment
Share on other sites

  • 2 weeks later...

Hi

I'm trying to catch a 302 redirect but when i disable redirects using _WinHttpSetOption, the request still goes on to the final page.

My code is based on one of your examples. Also i'm not sure if i'm using _WinHttpAddRequestHeaders correctly.

Any help would be appreciated, thanks.

; Initialize and get session handle
Global $hOpen = _WinHttpOpen()

_WinHttpSetOption($hOpen, $WINHTTP_OPTION_DISABLE_FEATURE, $WINHTTP_DISABLE_REDIRECTS)


; Get connection handle
Global $hConnect = _WinHttpConnect($hOpen, "u.to")


; Request
Global $hRequest = _WinHttpOpenRequest($hConnect, "GET", "/6GECAQ")

_WinHttpAddRequestHeaders($hRequest, "Host: u.to")
_WinHttpAddRequestHeaders($hRequest, "User-Agent: Sausage Head/5.0")


_WinHttpSendRequest($hRequest)

_WinHttpReceiveResponse($hRequest)


Global $sHeader = _WinHttpQueryHeaders($hRequest)


; Close handles
_WinHttpCloseHandle($hRequest)
_WinHttpCloseHandle($hConnect)
_WinHttpCloseHandle($hOpen)


MsgBox(0, "Header", $sHeader)
Link to comment
Share on other sites

If you want to disable redirects globally, you have to use

_WinHttpSetOption($hOpen, $WINHTTP_OPTION_REDIRECT_POLICY, $WINHTTP_OPTION_REDIRECT_POLICY_NEVER)

$WINHTTP_OPTION_DISABLE_FEATURE works only for request handles, in your case $hRequest.

This infomration can be found in the Remarks-section here

The two calls to _WinHttpAddRequestHeaders are unneccessary since Host is automatically set and the User-Agent is set with _WinHttpOpen

*GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

Link to comment
Share on other sites

If you want to disable redirects globally, you have to use

_WinHttpSetOption($hOpen, $WINHTTP_OPTION_REDIRECT_POLICY, $WINHTTP_OPTION_REDIRECT_POLICY_NEVER)

$WINHTTP_OPTION_DISABLE_FEATURE works only for request handles, in your case $hRequest.

This infomration can be found in the Remarks-section here

The two calls to _WinHttpAddRequestHeaders are unneccessary since Host is automatically set and the User-Agent is set with _WinHttpOpen

Thanks for the quick reply. All working now, typical i missed the one setting when looking at the options.

I have one scenario where i need to replicate a feature of cURL

(SSL) This option explicitly allows curl to perform "insecure" SSL connections and transfers. All SSL connections are attempted to be made secure by using the CA certificate bundle installed by default. This makes all connections considered "insecure" fail unless -k/--insecure is used.

I'm using cURL just now a few functions but trying to move them in AutoIt. For the above, i'm grabbing a link from multiupload.com and it's redirecting to rapidshare which seems to use https. I use the -k option to get around the certificate issue which seems to get me the data required.

I've tried setting a few options in WinHTTP but no luck. Do you have any idea how to do this at all? Thanks again.

WINHTTP_OPTION_CLIENT_CERT_CONTEXT seems to be the nearest option but i'm not sure how to get this working with WinHTTP.au3 as it doesn't seem supported.

Edited by Fly By Night
Link to comment
Share on other sites

@trancexx

When submitting a post form with a file, is it possible to :

-Avoid the gui to freeze

-Have a progress bar of file upload/form submit ?

Br, Firefox.

You can do that with AutoItObject. Compile server script to a3x and include it with installation. Make it export upload object. It would be very advanced besides simple. Use your imagination.
Link to comment
Share on other sites

As an alternative, do the post manually. Send the data in chunks with _WinHttpSendData. To improve the GUI-response, you could create a thread in assembler that sends the data. (The thread could be in a DLL, too)

Edited by ProgAndy

*GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

Link to comment
Share on other sites

As an alternative, do the post manually. Send the data in chunks with _WinHttpSendData.

Good idea, not sure I will be able to make it work.

To improve the GUI-response, you could create a thread in assembler that sends the data. (The thread could be in a DLL, too)

That's what I want but with my knowledge it's impossible...

Br, FireFox.

Link to comment
Share on other sites

I have a problem working with this API: http://linksave.in/api Here it's what it says:

For registered users:

The following data has to be sent by POST to our API:

They are:

URL: http://linksave.in/protect?api=[username]:[Password]

Field name: Value:

*save = TRUE

*links = [Links](seperated each by a line break "\n")

mirrors = [Mirrorlinks](seperated each by a line break "\n")

foldername = [Name of the folder]

myprotection = container_js (Container and webprotection)

container_plain (Container and premiumlinks)

container (only container

plain (only Premiumlinks)

js (only Webprotection)

container_types = rsdf ccf and/or dlc(not seperated)

container_name = [only Webprotection](if empty then foldername)

category = [name or number of the cateorgy, in which the folder will be moved; 0 for no category]

advertisement =

banner

bannerurl = [bannerurl](URL to bannerpicture)

bannerlink = [bannerlink](Link banner with this URL)

location = captchaseite(Show banner on captchapage)

frame(Show banner in hosterframe)

unten(Show banner below the links)

oben(Show banner above the links)

adminpassword = [adminpassword](if empty then random password)

visitorpassword = [Password to visit the folder]

cover = [Describing picture of the folder contents]

website = URL to your website

captcha = on or off

notify = 1 or 0 (Notification if files are offline)

email = [E-mail-address for notifications]

* = Required

Improtant: If you leave one or more fields empty, the corresponding value from your userCP-settings will apply.

Return values:

Standard = http://linksave.in/[Folder-ID]

[On error(s)] = ERROR

[Exact Errormessage(s)](seperated each by"|")

The problem that I found is that I find the documentation quite ambiguous or maybe it's my lack of experience, anyway I coded this:

#include <WinHttp.au3>

Global $sUserName = "Myuser"
Global $sPassword = "Mypass"
Global $sDomain = "www.linksave.in"
Global $sLinks = "http://www.fileserve.com/file/bByhbBm"
Global $sAdditionalData = "save=TRUE&links="&$sLinks&"foldername=testfolder&captcha=off"
;Global $sAdditionalData = "ordnername=testfolder&links=http%3A%2F%2Fwww.fileserve.com%2Ffile%2FbByhbBm"& _
;"myschutz=container_js&container_rsdf=1&container_ccf=1&container_dlc=1&captcha=N"

Global $hOpen = _WinHttpOpen("Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.6) Gecko/20100625 Firefox/3.6.6")

Global $hConnect = _WinHttpConnect($hOpen, $sDomain)

Global $hRequest = _WinHttpOpenRequest($hConnect, "POST","/protect?api="&$sUserName&":"&$sPassword)

_WinHttpSendRequest($hRequest, "Content-Type: application/x-www-form-urlencoded", $sAdditionalData)

_WinHttpReceiveResponse($hRequest)

Global $sReturned
If _WinHttpQueryDataAvailable($hRequest) Then
    Do
        $sReturned &= _WinHttpReadData($hRequest)
    Until @error
EndIf

_WinHttpCloseHandle($hRequest)
_WinHttpCloseHandle($hConnect)
_WinHttpCloseHandle($hOpen)

MsgBox(0, "Returned", $sReturned)
ConsoleWrite($sReturned)
FileWrite(@ScriptDir&'/htmlreturned.html',$sReturned)

I even saved a link manually and traced the process with live http headers in firefox. I saw that the additional data was sent in german so I try that -That's the 'Global...' that is commented in the code- but it didn't function either. In both cases it returns the page in the html as if I had used a get request and not http://linksave.in/[Folder-ID] or ERROR :huh2: I'm quite puzzled. Could you help me or give me some directions? Thanks for your help!

Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...