Handle Events from WinHttpRequest - events

A program I use runs .VBS scripts
So, in VBScript how can you handle the OnResponseFinished event for a WinHttpRequest object?
Set oHTTP = CreateObject("WinHttp.WinHttpRequest.5.1")
oHTTP.Open "GET", "http://www.google.com", True
oHTTP.Send

I was trying to get some code executed when the winhttp response comes (using VBScript inside HTA file). You may consider putting your event code right after the send. Using the following code, the user interface does not hang when waiting for the response:
Set objHTTP = CreateObject("WinHttp.WinHttpRequest.5.1")
objHTTP.Open "GET", "http://www.google.com", True
objHTTP.Send
objHTTP.WaitForResponse 'pauses execution, but does not hang UI
'from now on, execution only takes effect after completion of the response:
msgbox objHTTP.responseText 'an example of what can be done with the response
This seems to be the same as synchronous winhttp for script files, which can be what you are looking for. So, the only difference may be noticed when using an user interface.

Change the third paramater in the call to the Open method to false. Then place the code you would have in OnResponseFinished after the call to send.

Use WScript's CreateObject not the built in one for event handler.
Set oHTTP = WScript.CreateObject(
"WinHttp.WinHttpRequest.5.1",
"oHTTP_"
)

I'll admit his isn't a great answer, but the usual way to register VBScript events is to use the GetRef function to get a reference to the event handler, eg with an MSXML2.XMLHTTP object:
Set oHTTP = CreateObject("MSXML2.XMLHTTP")
oHTTP.Open "GET", "http://www.google.com", True
oHTTP.OnReadyStateChange = GetRef("oHTTP_OnReadyStateChange")
Sub oHTTP_OnReadyStateChange
' do something
End sub
oHTTP.Send
The trouble is, I tried it for your code, ie
Set oHTTP = CreateObject("WinHttp.WinHttpRequest.5.1")
oHTTP.Open "GET", "http://www.google.com", True
oHTTP.OnResponseFinished = GetRef("oHTTP_OnResponseFinished")
Sub oHTTP_OnResponseFinished
' do something
End sub
oHTTP.Send
and it didn't work, getting the error
Object doesn't support this property or method: 'oHTTP.OnResponseFinished'
but perhaps this can give you a starting point , or maybe you can use the MSXML2 library instead?
Just updating this answer with the other way of handling COM events - use the second parameter for the CreateObject function which allows you to specify the function prefix which connects functions to objects, eg
Set oHTTP = CreateObject("WinHttp.WinHttpRequest.5.1", "oHTTP_")
oHTTP.Open "GET", "http://www.google.com", True
Sub oHTTP_OnResponseFinished
' do something
End sub
oHTTP.Send
unfortunately, this doesn't work either - it must be that the IWinHttpRequestEvents interface is inaccessible

I checked the Windows Registry and there appears to be a number of Microsoft objects that do nearly the same thing:
Microsoft.XMLHTTP {ED8C108E-4349-11D2-91A4-00C04F7969E8}
MSXML2.XMLHTTP {F6D90F16-9C73-11D3-B32E-00C04F990BB4}
WinHttp.WinHttpRequest.5.1 {2087c2f4-2cef-4953-a8ab-66779b670495}
MSXML2.ServerXMLHTTP {AFBA6B42-5692-48EA-8141-DC517DCF0EF1}
What works for me is Microsoft.ServerXMLHTTP which allows setting of the onreadystatechange in VBScript. The "MSXML2.ServerXMLHTTP" handles redirecting websites (e.g. google.com) which makes it a better choice over "Microsoft.XMLHTTP".
Dim xmlhttp ' global so can be accessed in OnStateChange
Sub OnStateChange
If xmlhttp.readystate = 4 Then
' React to xmlhttp.responseText
MsgBox xmlhttp.responseText
End If
End Sub
Set xmlhttp = CreateObject("Microsoft.XMLHTTP")
xmlhttp.open "GET", "http://www.google.com/", true
xmlhttp.onreadystatechange = GetRef("OnStateChange")
xmlhttp.send
' do something else whilst xmlhttp is running in the background
MsgBox "Pausing so that OnStateChange can fire!"

It does need seem to be possible according to this (go to remarks) you can only access the error state with Err. Microsoft's documentation is lousy.

I found that I can get this to work Asynchronously by using the 'waitForResponse' with parameter '0' for the timeout method as a flag.
IE:
oHTTP.Open "GET", "http://www.google.com", True
oHTTP.Send
Do While oHTTP.waitForResponse(0) = False
'do stuff while waiting for it to be done
WScript.Sleep 200 'sleep for 0.2 seconds between checks as not waste CPU
DoEvents
Loop
'Once the loop is exited, the response is finished
MsgBox oHTTP.ResponseText

Related

Download and save a webpage using vbscript

I am trying to give users the option to download and save a webpage to where ever they want. I have been looking all over for a solution but nothing seems to be working. I am using vbscript in classic asp.
This is what I tried last
dim xHttp: Set xHttp = createobject("Microsoft.XMLHTTP")
dim bStrm: Set bStrm = createobject("Adodb.Stream")
xHttp.Open "GET", "" &Session("ServerURL") & "/idautomation/IDAutomationStreamingLinear.aspx?D=MAPS$"&request.QueryString("catcode")&"%25"&request.QueryString("typecode")&"&X=0.09&BH=3&S=0&CC=T&LM=5&TM=7.5&ST=F", False
xHttp.Send
with bStrm
.type = 1 '//binary
.open
.write xHttp.responseBody
.savetofile "d:\DownloladPdf.pdf", 2 '//overwrite
end with
but its throwing a "Write to file failed. " on the .savetofile line.
I want the user to be able to chose where to save it to...
You can't save to the users computer from server side code VBscript directly as this would be a major security issue allowing drive by compromises of people browsing a web page. The reason possibly that it is throwing an error is that it is trying to save it server side, but there is no D: on the server.
Instead you want to serve the PDF to the browser using Response and let the browser display or save the PDF.
The below example is using a bytes array rather than a stream, but it should be similar. If you want to force it to download rather than show in the browser, change the content-disposition to attachment. You can also change the filename to whatever you like.
if Len(pdfBytes) > 0 then
Response.Clear()
Response.ContentType = "application/pdf"
Response.Charset = ""
Response.AddHeader "Cache-Control", "public, max-age=1" ' Setting Cache-Control to max-age=1 rather than no-cache due to IE8 bug
Response.AddHeader "content-disposition","inline; filename=filename.pdf"
Response.Buffer = True
Response.Expires = 0
Response.BinaryWrite(pdfBytes)
Response.Flush
Response.End
Response.Close
end if

Getting response text from server

I am trying to get the text inside a file in the folder structure of my site using the Microsoft.XmlHttp, then compare it with my version.txt on my local PC. if the same, it will prompt a message that it contains the same version, else it will display the opposite.
URL="http://www.example.org/sites/default/files/version.txt"
Set WshShell = WScript.CreateObject("WScript.Shell")
Set http = CreateObject("Microsoft.XmlHttp")
On Error Resume Next
http.open "GET", URL, False
http.send ""
if http.status = 200 Then
server_version = http.responseText
End if
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objClientVersion = objFSO.OpenTextFile("C:\mcgfiles\avp\hash.txt",1)
client_version = objClientVersion.ReadLine
comparison = StrComp(server_version, client_version)
If comparison = 0 Then
Wscript.Echo "the same"
Else
Wscript.Echo "not the same"
End If
kinda work, but each time i try to change the contents of the http://www.example.org/sites/default/files/version.txt from my server, this scripts still gets the old value: for example, the values of the http://www.example.org/sites/default/files/version.txt before is 123456, when I run the script it gets the 123456. When I change the value to 654321 and run this script, it still gets the old value which is 123456. Help Thanks
Disable response caching:
http.open "GET", URL, False
http.setRequestHeader "Cache-Control", "no-cache,max-age=0"
http.setRequestHeader "Pragma", "no-cache"
http.send
Also, you may want to replace ReadLine with ReadAll, because the former will only read the first line of the local file, while the HTTP request returns the entire remote file.

VBScript Code: Object required error

Guys
I just wrote a vbs code snippet to automatically post in a forum. That's just for convenience. I encountered a wired problem:
I have several accounts. When I login as some accounts and use the script to automatically post, everything is OK. However, when I login as the other accounts and run the script, I got the error:
Error : Object required "getElementById(...)"
Code : 800a01a8
Source : Microsoft VBScript runtime error
I'm sure the object exists because I get it in the source of the webpage. I feel the error occurred randomly and I cannot get the regularity.
The script is ran in a Windows 8 OS and the browser is IE9. I'm a new learner of vbs and I don't know how to debug it. So I hope someone can help me. You can give me some clue.
Here is my code snippet:
Option Explicit
Dim IEApp
Dim iURL1
Dim iURL2
Dim iURL3
Dim iURL4
Dim iURL5
Set IEApp = CreateObject("InternetExplorer.Application")
iURL1="http://bbs.dealmoon.com/thread-299027-1-1.html"
iURL2="http://bbs.dealmoon.com/thread-299195-1-1.html"
iURL3="http://bbs.dealmoon.com/thread-299018-1-1.html"
iURL4="http://bbs.dealmoon.com/thread-299015-1-1.html"
iURL5="http://bbs.dealmoon.com/thread-299014-1-1.html"
Open iURL1
Open iURL2
Open iURL3
Open iURL4
Open iURL5
WScript.Echo("Done!")
Sub Wait(IE)
Do
WScript.Sleep 500
Loop While IE.ReadyState < 4 And IE.Busy
Do
WScript.Sleep 500
Loop While IE.ReadyState < 4 And IE.Busy
End Sub
Sub Post(IE)
Dim count
For count=0 To 9
With IE.Document
.getElementById("fastpostmessage").innerHTML = "good"
.getElementById("fastpostsubmit").click
Wait IE
WScript.Sleep GetRandom(7,15)
End With
Next
End Sub
Sub Open(PageURL)
IEApp.Visible = False
IEApp.Navigate PageURL
Wait IEApp
Post IEApp
End Sub
Function GetRandom(floor,ceil)
Randomize
GetRandom=Int((ceil - floor + 1) * Rnd + floor)*1000
End Function
You should call your POST routine after all the HTML content is loaded, for example in DOMContentLoaded or window.onload (for IE<9).
You dimmed IEApp, created the object, but you are not using it when trying to get the element ID. Your With block should look like this:
With IEApp.Document
.getElementById("fastpostmessage").innerHTML = "good"
.getElementById("fastpostsubmit").click
Wait IEApp
WScript.Sleep GetRandom(7,15)
End With
There are a few other places you only have IE instead of IEApp. Clear those up and your code should run fine.

Is XMLHTTP's responsebody working asynchronously in VB6?

We have a SSRS integrated sharepoint server. I am trying to get a report exported as PDF from it.
(I had to do like this, because my url is too long. I would rather use Shell command to do like this, although this looks like a better solution.)
Here'is my code:
Dim request as New XMLHTTP
Dim oStream as New Stream
Dim aBunchOfMiliseconds as Long
Dim fileLocation as String
Dim reportUrl as String
aBunchOfMiliseconds = 500
reportUrl = "http://www.mySharepointDomain.com/_vti_bin/ReportServer?http://www.mySharepointDomain.com/sites/AFolderHere/OOAnotherFolder/BlaBlaReportFolder/FolderFolder/AhTheLastOne/AtLeastMyReportFile.rdl&rs:Command=Render&rc:Toolbar=true&rs:Format=PDF&Parameter1=ABC &Parameter2=1&Parameter3=1&TheLastParameter=IllBeDamned&rs%3aParameterLanguage=ln-LN"
request.Open "GET", reportUrl
request.setRequestHeader "WWW-Authenticate", "NTLM" 'For impersonation
request.Send 'Go get it Bruce
If request.Status = 200 Then 'Are you successful?
oStream.Type = adTypeBinary
oStream.Open
oStream.Write request.responseBody 'Here's the problematic part
Sleep(aBunchOfMiliseconds) 'If I don't do this, file will be corrupted
oStream.SaveToFile fileLocation, adSaveCreateOverWrite
oStream.Close
End If
Set oStream = Nothing
Set request = Nothing
If I comment out the "Sleep" line, I will have a corrupted file that can not open. This code works fine but I found it ridiculus to use "Sleep" there.
Is there any way me to understand that the data copy operation is completed?
Oh I get it.
I've missed to say that "this is not an async call".
request.Open "GET", reportUrl, False

msxml3.dll Access Denied

I have the following code:
Function filejson(json)
Dim objStream, strData
Set objStream = CreateObject("ADODB.Stream")
objStream.CharSet = "utf-8"
objStream.Open
objStream.LoadFromFile(json)
strData = objStream.ReadText()
filejson = strData
End Function
Function http2json(url)
Set http = CreateObject("Microsoft.XmlHttp")
http.open "GET", url, FALSE
http.send "" '<------- Line 13
http2json=http.responseText
End Function
Function str2json(json,value)
Set scriptControl = CreateObject("MSScriptControl.ScriptControl")
scriptControl.Language = "JScript"
scriptControl.AddCode("x="& json & ";")
str2json= scriptControl.Eval( "x"& value )
End Function
Function get_json_from_file(json,value)
get_json_from_file=str2json(filejson(json),value)
End Function
Function get_json_from_http(url,value)
get_json_from_http=str2json(http2json(url),value)
End Function
Function save_json_from_http(url,loc)
Set fso = CreateObject("Scripting.FileSystemObject")
fullpath = fso.GetAbsolutePathName(loc)
Dim objStream, strData
Set objStream = CreateObject("ADODB.Stream")
objStream.CharSet = "utf-8"
objStream.Open
objStream.WriteText http2json(url)
objStream.SaveToFile fullpath, 2
save_json_from_http=fullpath
End Function
Wscript.Echo save_json_from_http("http://api.themoviedb.org/3/authentication/session/new?api_key=#####some_api_key_example#####&request_token=#####some_default_request_token######&_ctime_json_=1372670635.164760555","tmdb\temp\_tmdb_sock_w.164519518.2109")
When I run this code, I get the following error.
If I remove &request_token=#####some_default_request_token###### it works just fine.
I also tried this: I added again the request_token, and I just typed a random character in it, for example, rexfuest_token, and strangely it worked. It seems there's a wrong parse in msxml3.dll. with request_token word.
Ideas?
This problem could be related to the security issues in Windows. The best way to fix it is to replace Microsoft.XmlHttp/MSXML2.XMLHTTP with MSXML2.ServerXMLHTTP.
I see the topic is almost 2 years old and most likely the topic starter has solved is issue. I have experienced the same issue couple hours ago and google provided me several links. There are some of them:
https://social.msdn.microsoft.com/Forums/en-US/1abda1ce-e23c-4d0e-bccd-a323aa7f2ea5/access-is-denied-while-using-microsoftxmlhttp-to-get-a-url-link-in-vbscript-help?forum=xmlandnetfx
https://support.webafrica.co.za/index.php?/Knowledgebase/Article/View/615/41/msxml3dll-error-80070005-access-is-denied---loading-xml-file
http://www.experts-exchange.com/Programming/Languages/Scripting/ASP/Q_27305017.html
Try with a more recent version:
Set http = CreateObject("Msxml2.XMLHttp.6.0")
It could also be an issue with your Internet security settings (see here). Open the Internet Options applet in the Control Panel, select the zone for the website (probably "Trusted sites") in the Security tab and click Custom level….
In the section Miscellaneous set Access data sources across domains to Enabled.
Also can change URL from http to https. Me helps
For me the solution was to add the URL in trusted sites.
Internet explorer browser > Tools > Internet options > Security > Trusted sites > Sites > Add the URL under "Add this website to the zone: " and click add and save.

Resources