I'm writing a vbscript to pull some data from a webpage, strip out a few key pieces of information and write those to a file.
At the moment my script to access the pages and save the file contents to a string is this:
Set WshShell = WScript.CreateObject("WScript.Shell")
Set http = CreateObject("Microsoft.XmlHttp")
'Load Webpage where address is URL
http.open "GET", URL, FALSE
http.send ""
'Assign webpage contents as a string to variable called Webpage
WEBPAGE = http.responseText
I need to save the content to a string so I can use a regular expression on it to pull out the content that I need.
This script works perfectly, EXCEPT for when the pages contain non-standard characters (such as é). When the page contains something like this, the script throws up an error and stops.
I'm guessing this is something to do with the encoding, but I can't work out how to fix it. Can anyone point me in the right direction? Thanks guys
Edit
Thanks to the help here I realised I've asked the wrong question! It turns out I was downloading the content fine - the problem was, afterwards I was trying to edit it and write it out to a file, and the file was in the wrong format. I had this:
Set objTextFile = objFSO.OpenTextFile(OutputFile, 8, True,)
Changing it to this:
Set objTextFile = objFSO.OpenTextFile(OutputFile, 8, True, -1)
Seems to have fixed it. What a crazy world, eh? Thanks for the help.
You may need to set the correct header blocks before send
eg the following is an example only. You will need to find out what this is exactly for your website
http.open "GET", URL, FALSE
http.SetRequestHeader "User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)"
http.SetRequestHeader "Accept", "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5"
http.SetRequestHeader "Accept-Language", "en-us,en;q=0.5"
http.SetRequestHeader "Accept-Charset", "ISO-8859-1,utf-8;q=0.7,*;q=0.7"
http.send ""
EDIT:
What about this instead. It works ok here
Dim XMLHttpReq,URL,WEBPAGE
Const Eacute = "%C3%89"
Set XMLHttpReq = CreateObject("MSXML2.ServerXMLHTTP")
URL = "http://en.wikipedia.org/wiki/%C3%89"
'Load Webpage where address is URL
XMLHttpReq.Open "GET", URL, False
XMLHttpReq.send ""
'Assign webpage contents as a string to variable called Webpage
WEBPAGE = XMLHttpReq.responseText
WEBPAGE = Replace(WEBPAGE, Eacute, "É")
'Debug.Print WEBPAGE
The E acute in this case returns as string %C3%89 and you can force it to whatever character you choose if required.
EDIT2:
Just to add, if you're doing this with VBScript you may find this method useful
Dim XMLHttpReq, URL, WEBPAGE, fso, f
Const Eacute = "%C3%89"
Set XMLHttpReq = CreateObject("MSXML2.ServerXMLHTTP")
URL = "http://en.wikipedia.org/wiki/%C3%89"
XMLHttpReq.Open "GET", URL, False
XMLHttpReq.send ""
WEBPAGE = XMLHttpReq.responseText
Save2File WEBPAGE, "C:\Users\osknows\Desktop\test.txt"
Sub Save2File (sText, sFile)
Dim oStream
Set oStream = CreateObject("ADODB.Stream")
With oStream
.Open
.CharSet = "utf-8"
.WriteText sText
.SaveToFile sFile, 2
End With
Set oStream = Nothing
End Sub
Related
I want to establish a secure connection with my server which only supports TLS 1.2 and upwards.
I am adding the following line to my VB.NET applications to enable communication with my https server:
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12
However, I also still have some VB6 apps which also need to use https server.
And the above line is not available for VB6, and the code throws "Error Occurred in the Secure Channel Support". If I use it on http instead of https, it works fine.
How could I achieve the same for VB6?
Thank you!
Btw, this is my code:
Public Function GetHTTPResponse(Byval uSomeInput) As String
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 'required in order to use https!!!
Dim nReq As Net.WebRequest = Net.WebRequest.Create("https://domain.xyz/answer.php")
nReq.Method = "Post"
nReq.ContentType = "application/x-www-form-urlencoded"
Dim nReqStream As IO.Stream = nReq.GetRequestStream()
Dim nASCIIEncoding As New System.Text.ASCIIEncoding
Dim btPostData As Byte() = Nothing
btPostData = nASCIIEncoding.GetBytes("&MyPHPInput=" & uSomeInput)
nReqStream.Write(btPostData, 0, btPostData.Length)
nReqStream.Close()
Dim reader As New IO.StreamReader(nReq.GetResponse().GetResponseStream())
Dim sRet As String = reader.ReadToEnd
Return sRet
End Function
And this is the same code in VB6, but in VB6, I can't (to my knowledge) not set the Tls12 security protocol:
Public Function GetHTTPResponse(ByVal uSomeInput) As String
'How do I set Tls12 protocol here??
Dim xmlhttp As Object
Set xmlhttp = CreateObject("MSXML2.ServerXMLHTTP")
xmlhttp.Open "POST", "https://domain.xyz", False
xmlhttp.SetRequestHeader "Content-Type", "application/x-www-form-urlencoded" & VBA.Chr(10) & VBA.Chr(13)
xmlhttp.Send pConvertStringToByte("https://domain.xyz/answer.php?MyPHPInput=" & uSomeInput)
GetHTTPResponse = xmlhttp.responseText
End Function
Edit:
I have followed the advice to try using WinHttp.WinHttpRequest.5.1 instead as discussed here.
It seems to work, but for some reason, the variables are not being transferred / recognized by the script, while they were recognized with my old approach using MSXML2.ServerXMLHTTP.
This is my code:
Public Function GetHTTPResponse(ByVal uSomeInput) As String
Dim xmlhttp As Object
Set xmlhttp = CreateObject("WinHttp.WinHttpRequest.5.1")
'force TLS 1.2
xmlhttp.Option(9) = 2048
xmlhttp.Option(6) = True
xmlhttp.Open "POST", "https://domain.xyz", False
xmlhttp.SetRequestHeader "Content-Type", "application/x-www-form-urlencoded" & VBA.Chr(10) & VBA.Chr(13)
xmlhttp.Send pConvertStringToByte("https://domain.xyz/answer.php?MyPHPInput=" & uSomeInput)
GetHTTPResponse = xmlhttp.responseText
End Function
Does anybody see why my old byte array is not accepted for "WinHttp.WinHttpRequest.5.1" while it work for "MSXML2.ServerXMLHTTP"?
Try this one:
' Define uSomeInput's data type, otherwise it's passed as a Variant, which might or might not be what we intended
Public Function GetHTTPResponse(ByVal uSomeInput As String) As String
' Use early instead of late binding
Dim xmlhttp As WinHttp.WinHttpRequest
Set xmlhttp = New WinHttpRequest
' force TLS 1.2
xmlhttp.Option(9) = 2048
xmlhttp.Option(6) = True
xmlhttp.Open "POST", "https://domain.xyz", False
xmlhttp.SetRequestHeader "Content-Type", "application/x-www-form-urlencoded" & vbNewLine
' Let the webserver know the size of the data
xmlhttp.SetRequestHeader "Content-Length", CStr(LenB(uSomeInput)) & vbNewLine
xmlhttp.Send pConvertStringToByte("https://domain.xyz/answer.php?MyPHPInput=" & uSomeInput)
' Not sure why the string to byte array conversion is necessary
' Could just try the string as well
xmlhttp.Send "https://domain.xyz/answer.php?MyPHPInput=" & uSomeInput
GetHTTPResponse = xmlhttp.ResponseText
End Function
If everything else fails and you require a VB6 solution and therefore are willing (or forced) to spend money ($ 395) on a commercial component, have a look at SocketTools. Although tempting, I suggest taking the Library over the ActiveX edition (which is just a wrapper of the former, IMHO). I've used SocketTools in VB6 with great success in the past (since its 6.x version, IIRC). I started using it, because I faced a very similar task to yours: I had to support SFTP transfer in my VB6 application.
Edit: Problem is solved. For some reason the Base64Encode function was putting a line break in the output string, something I didn't notice until I response.write the output and looked at the source code of the page instead of the compiled page.
I'm trying to send JSON to a remote server in order to get back a JSON response (Basically I send them data, they perform calculations based on my data and send back different data). However instead of getting data back the server tells me the request failed authentication.
The Authentication involves sending a base64 encoded string, username, and password combined. These values can change so I'm using variables to pass the information on. This does not work, however if I enter the fully encoded value as a string it does work.
Function GetAPdataPost(sSendHTML, sURL)
dim apHTTP
dim sHTTPResponse
dim API_KEY
dim API_PWD
dim auth
API_KEY = "fred"
API_PWD = "barney"
auth = Base64Encode(API_KEY & ":" & API_PWD)
Set apHTTP = Server.CreateObject("MSXML2.ServerXMLHTTP")
apHTTP.Open "POST", sURL, false
apHTTP.setRequestHeader "Content-Type", "application/json; charset=UTF-8"
apHTTP.setRequestHeader "Authorization","Basic ZnJlZDpiYXJuZXk=" '<-- works
apHTTP.setRequestHeader "Authorization", "Basic " & auth '<-- doesn't work
apHTTP.setRequestHeader "Content-Length", len(sSendHTML)
apHTTP.setRequestHeader "Accept", "*/*"
apHTTP.setRequestHeader "Account-Number", "00000004"
apHTTP.setRequestHeader "Cache-Control", "no-cache"
apHTTP.setRequestHeader "Connection", "close"
On Error Resume Next
apHTTP.send sSendHTML
sHTTPResponse = apHTTP.responseText
If Err.Number = 0 Then
GetAPdataPost = sHTTPResponse
Else
GetAPdataPost = "Something went wrong: " & Err.Number
End If
On Error Goto 0
Set apHTTP = Nothing
End Function
Using the first line result in a proper response form the server, a valid JSON string with all the required data. The second line results in a JSON string saying "The request failed authentication".
So aside from typing out the Base64 encoded string how do I get a variable to be recognised as a valid string?
I should just note that I have tried surrounding auth with double quotes ("") and Chr(34) to no avail.
Edit: Base64 Encode function.
Function Base64Encode(sText)
Dim oXML, oNode
Set oXML = CreateObject("Msxml2.DOMDocument.3.0")
Set oNode = oXML.CreateElement("base64")
oNode.dataType = "bin.base64"
oNode.nodeTypedValue =Stream_StringToBinary(sText)
Base64Encode = oNode.text
Set oNode = Nothing
Set oXML = Nothing
End Function
Function Stream_StringToBinary(Text)
Const adTypeText = 2
Const adTypeBinary = 1
'Create Stream object
Dim BinaryStream 'As New Stream
Set BinaryStream = CreateObject("ADODB.Stream")
'Specify stream type - we want To save text/string data.
BinaryStream.Type = adTypeText
'Specify charset For the source text (unicode) data.
BinaryStream.CharSet = "us-ascii"
'Open the stream And write text/string data To the object
BinaryStream.Open
BinaryStream.WriteText Text
'Change stream type To binary
BinaryStream.Position = 0
BinaryStream.Type = adTypeBinary
'Ignore first two bytes - sign of
BinaryStream.Position = 0
'Open the stream And get binary data from the object
Stream_StringToBinary = BinaryStream.Read
Set BinaryStream = Nothing
End Function
The Base64Encode function was putting a line break in the output string, something I didn't notice until I response.write the output and looked at the source code of the page instead of the compiled page.
Always remember to look at the raw data, not just the displayed data (i.e. not like me)
I built some code to retrieve stock data from Yahoo as a CSV file, and it works fine. When I change the URL to the perfectly legal version that recalls minutewise data from Google instead, it fails on the
objHTTP.open "GET", strURL, False
statement.
The following code shows both URLs, although obviously only the final one is called. Both URLs work when posted into the address bar of a browser.
Can anyone explain why the call to Google's page won't Open?
option explicit
Dim objHTTP
dim strURL
dim objFile
dim objFSO
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objHTTP = CreateObject("MSXML2.XMLHTTP")
' WORKS:
strURL = "http://real-chart.finance.yahoo.com/table.csv?s=UPRO&a=04&b=21&c=2016&d=04&e=31&f=2016&g=d&ignore=.csv"
' DOES NOT WORK:
strURL = "www.google.com/finance/getprices?q=UPRO&i=60&p=20d&f=d,c,v,k,o,h,l&df=cpct&auto=0&ei=Ef6XUYDfCqSTiAKEMg"
objHTTP.open "GET", strURL, False
objHTTP.send
msgbox objHTTP.responseText
Set objFile = objFSO.CreateTextFile _
("Yahoo.csv", 2)
objFile.Write objHTTP.ResponseText
objFile.Close
You are missing http:// from the broken URL. When I added this, I got response data.
I am having a VBScript which gets invoked from a 3rd party application, the script gets the data from the 3rd party application and opens the URL in an IE browser by passing the data in POST format. The script works fine when I use http as the protocol but the moment I use https, the server side code (request.getParameter("param1")) complains that it is not able to find the parameter in the request object. The script is called by passing the URL and the data. e.g. run.vbs https://xyz.com?param1=1234. Following is the vbscript for your kind perusal. Can you please let me know what I am missing when I am using https as the protocol. Any help is highly appreciated. Many thanks.
If WScript.Arguments.Count = 1 Then
uri = WScript.Arguments.Item(0)
'WScript.Echo "Arguments " & uri
Set WshNetwork = WScript.CreateObject("WScript.Network")
'WScript.Echo "Current User Name: " & WshNetwork.UserName
filename="C:\Documents and Settings\"+WshNetwork.UserName+"\Application Data\XYZ\Profiles\default\Settings.xml"
'WScript.Echo "Current User fileName: " & filename
Set xmlDoc = CreateObject("Microsoft.XMLDOM")
xmlDoc.Async = "False"
xmlDoc.Load(filename)
strQuery = "Agent"
Set colItem = xmlDoc.getElementsByTagname(strQuery)
For Each objItem in colItem
Agentid = objItem.getAttribute("Login")
'MsgBox "AgentId = " + AgentID
Next
'uri = uri+"^&agentid="+Agentid
uri = uri+"&agentid="+Agentid
pos = InStr(uri,"?")
extracteduri = Mid(uri,1,pos-1)
params = Mid(uri, pos+1)
postdata = Str2Bytes(params,"us-ascii")
header = "Content-Type: application/x-www-form-urlencoded"
Set IE = CreateObject("InternetExplorer.Application")
'IE.Navigate "about:blank"
'IE.AddressBar = True
'IE.ToolBar = True
'IE.StatusBar = True
IE.Visible = True
'WScript.Sleep 2000
Set shl = WScript.CreateObject("WScript.Shell")
shl.SendKeys "% X"
IE.Navigate extracteduri, Nothing, Nothing, postdata, header
Wscript.Quit
Else
Wscript.Echo "Usage: RunURL.vbs <URL to invoke>"
Wscript.Quit
End If
Function Str2Bytes(Text, CharSet)
Const adTypeText = 2
Const adTypeBinary = 1
'Create Stream object
Dim BinaryStream 'As New Stream
Set BinaryStream = CreateObject("ADODB.Stream")
'Specify stream type - we want To save text/string data.
BinaryStream.Type = adTypeText
'Specify charset For the source text (unicode) data.
If Len(CharSet) > 0 Then
BinaryStream.CharSet = CharSet
Else
BinaryStream.CharSet = "us-ascii"
End If
'Open the stream And write text/string data To the object
BinaryStream.Open
BinaryStream.WriteText Text
'Change stream type To binary
BinaryStream.Position = 0
BinaryStream.Type = adTypeBinary
'Ignore first two bytes - sign of
BinaryStream.Position = 0
'Open the stream And get binary data from the object
Str2Bytes = BinaryStream.Read
End Function
I am now using the below function to get the response from the server using https as the protocol and POST as the format but still the server is not able to see the parameter
Set req = CreateObject("MSXML2.ServerXMLHTTP")
'Set the below option to get rid of the "Certificate authority is invalid or
'incorrect, error code - 80072F0D" error
req.setOption 2, 13056
req.open "POST", extracteduri, False
req.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
encodedParams = Escape(params)
WScript.Echo "encodedParams: " & encodedParams
req.send encodedParams
WScript.Echo "req.responseText: " & req.responseText
Below are the encoded parameters
uui%3DU1%3D123456%26agentid%3D123456
The server still complains that the parameter is missing from the request object.
I am using the same script (XMLHTTP request) but I am encrypting the parameters using the Str2Bytes function (declared above)
Set req = CreateObject("MSXML2.ServerXMLHTTP")
req.setOption 2, 13056
req.open "POST", extracteduri, False
req.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
req.send postdata
WScript.Echo "req.responseText: " & req.responseText
I'd recommend using an XMLHTTPRequest instead of the Internet Explorer COM object. See here for an example. Note that you must encode special characters in the post data.
However, if you want to open the URL in IE anyway, you'd probably better stick with your original approach. In that case I'd check the server for more information about why the server side thinks it cannot find the parameter. Does the request even have a parameter named "param1"?
goal:
log into the web page
and save the html to a file for parsing later.
the html on the page is just a list of users and when they logged in and off.
When you load the web page up a javascript box pops up and asks for login information
i can fill this with SendKeys but i really want to do this without a window popping up
Set IE = CreateObject("InternetExplorer.Application")
set WshShell = CreateObject("WScript.Shell")
IE.Visible = False ' doesn't set IE page as invisible?????
IE.Navigate "https://mysite/site/console/client-log.jsp"
'how do i fill in the box ???
I'd suggest to use something like Fiddler to identify the request that does the actual login, and then use that information in an XMLHttpRequest.
url = "..."
filename = "..."
Set req = CreateObject("MSXML2.XMLHTTP.6.0")
req.open "POST", url, False
req.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
req.send "field1=foo&field2=bar&..."
Set fso = CreateObject("Scripting.FileSystemObject")
fso.OpenTextFile(filename, 2, True).WriteLine req.responseText
If the response is UTF-8 encoded you may need to use an ADODB.Stream object for saving the content.
Set stream = CreateObject("ADODB.Stream")
stream.Open
stream.Type = 2 'text
stream.Position = 0
stream.Charset = "utf-8"
stream.WriteText req.responseText
stream.SaveToFile filename, 2
stream.Close