Issue in parsing XML with Classic ASP (VBscript) - vbscript

I have the following code, which used to work perfectly, But now for somes reason, doesn't.
The XML I am reading is located at: https://forex.boi.org.il/currency.xml
The following code should parse the XMl and then save the USD/ILS exchange rate. As I say, it doesnt anymore, and I cant figure out whats wrong.
forexURL = "https://forex.boi.org.il/currency.xml"
getUSDRate = 0
MyRate = 0
Set xmlObj = Server.CreateObject("MSXML2.FreeThreadedDOMDocument")
xmlObj.async = False
xmlObj.setProperty "ServerHTTPRequest", True
xmlObj.Load(forexURL)
Set xmlList = xmlObj.getElementsByTagName("CURRENCY")
Set xmlObj = Nothing
x = 1
For Each xmlItem In xmlList
response.write "<p>" & xmlItem.childNodes(0).text
response.write "<p>" & xmlItem.childNodes(1).text
response.write "<p>" & xmlItem.childNodes(2).text
response.write "<p>" & xmlItem.childNodes(3).text
response.write "<p>" & xmlItem.childNodes(4).text
response.write "<p>" & xmlItem.childNodes(5).text
response.write "<p>___________________<br />" & x & "</p>"
if xmlItem.childNodes(2).text = "USD" then
MyRate = xmlItem.childNodes(4).text
exit for
end if
x = x +1
Next
Set xmlList = Nothing

I suspect (wild guess ahead) changes to the way SSL is handled on the server side as the cause of your trouble. Maybe they disabled older, more insecure ciphers in response to recent SSL bugs.
Like #John notes - when you change from MSXML2.FreeThreadedDOMDocument (which loads version MSXML2 version 3) to explicitly load the more modern version 6 (MSXML2.FreeThreadedDOMDocument.6.0) then the download of the document succeeds.
That being said I've made a few changes to your code, mostly to be more readable and make it fail visibly when the document load fails for some reason.
Note
the use of XPath
a helper function GetText() in place of blindly indexing into child nodes
the parseError check to make LoadXmlDocument fail non-silently
.
Option Explicit
Dim usdRate, x, currencies, curr
Set currencies = LoadXmlDocument("https://forex.boi.org.il/currency.xml")
usdRate = GetText(currencies, "//CURRENCY[CURRENCYCODE = 'USD']/RATE")
x = 1
For Each curr In currencies.getElementsByTagName("CURRENCY")
Response.Write "<p>" & GetText(curr, "NAME") & "</p>"
Response.Write "<p>" & GetText(curr, "UNIT") & "</p>"
Response.Write "<p>" & GetText(curr, "CURRENCYCODE") & "</p>"
Response.Write "<p>" & GetText(curr, "COUNTRY") & "</p>"
Response.Write "<p>" & GetText(curr, "RATE") & "</p>"
Response.Write "<p>" & GetText(curr, "CHANGE") & "</p>"
Response.Write "<p>___________________<br />" & x & "</p>"
x = x + 1
Next
' ----------------------------------------------------------------------
' loads an XML document from a URL and returns it
Function LoadXmlDocument(url)
Set LoadXmlDocument = CreateObject("MSXML2.FreeThreadedDOMDocument.6.0")
LoadXmlDocument.async = False
LoadXmlDocument.setProperty "ServerHTTPRequest", True
LoadXmlDocument.setProperty "SelectionLanguage", "XPath"
LoadXmlDocument.Load url
If LoadXmlDocument.parseError <> 0 Then
Err.Raise vbObjectError + 1, _
"LoadXmlDocument", _
"Cannot load " & url & " (" & LoadXmlDocument.parseError.reason & ")"
End If
End Function
' finds the first node that matches the XPath and returns its text value
Function GetText(context, xpath)
Dim node
Set node = context.selectSingleNode(xpath)
If node Is Nothing Then
GetText = vbEmpty
Else
GetText = node.text
End If
End Function

I just tried this on my machine. Try replacing
Server.CreateObject("MSXML2.FreeThreadedDOMDocument")
with
Server.CreateObject("Msxml2.DomDocument.6.0")
Edit
Server.CreateObject("MSXML2.FreeThreadedDOMDocument.6.0")
also seems to work

Related

Writing wrong values to log files after concurrent calls of a script

This code sample is part of a vbscript script that
is making HTTP POST requests for sending SMS through an API. For each SMS, I need a unique random ID. A description of the functions:
WriteLog (Create log files)
MoveLogFiles (Archiving old log files)
CreateGUID (Generate GUIDs for each SMS)
The problem here is when I write to the log file. I tried apache benchmark to stress test my script. In the log file, the smsID is not stored correctly. It is supposed to be unique for each http request. Instead I see the same ID written in many entries in the log file. How can I protect the variable so that it writes the appropriate value in the log file when the script is called multiple times?
Private smsID
smsID = CreateGUID(12)
'HTTP Request & Response
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
WriteLog smsID, "[SMS ID:" & smsID & "] Starting HTTP Request..."
WriteLog smsID, "[SMS ID:" & smsID & "] JSON to be sent: " & JSONStringNoPIN
WriteLog smsID, "[SMS ID:" & smsID & "] Sending HTTP Request..."
ASPPostJSON(smsID)
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
set JSONString = Nothing
set JSONStringNoPIN = Nothing
set JSONRequest = Nothing
logFilesDic.RemoveAll
Set logFilesDic = Nothing
WriteLog smsID, "[SMS ID:" & smsID & "] Finished..." & vbCrLf
Set smsID=Nothing
Function WriteLog(ByVal smsID_, ByVal psMessage)
Dim fs: Set fs = Server.CreateObject("Scripting.FileSystemObject")
' Check if the log file and folder exists
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
dim f, logSize, logDic
On Error Resume Next
Set f = fs.GetFile(logFile)
Set logDic = CreateObject("Scripting.Dictionary")
'logDic.Add "1", Now() & vbTab & "[SMS ID:" & smsID_ & "] Opening Log file: " & logFile
If Err.Number <> 0 Then
logDic.Add "1", Now() & vbTab & "[SMS ID:" & smsID_ & "] An error occured while opening the log file. Error #" & Err.Number & ": " & Err.Description
If Err.Number = 53 And Not fs.FileExists(logFile) Then
if Not fs.FolderExists Then
fs.CreateFolder logDirectory
End if
if Not fs.FileExists(logFile) Then
fs.CreateTextFile logFile
logDic.Add "2", Now() & vbTab & "[SMS ID:" & smsID_ & "] Log file was created: " & logFile
End if
Set f = fs.GetFile(logFile)
End if
End if
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Check if the log size exceeds the log size limit
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
logSize = f.Size
if logSize >= logMaxSize Then
logDic.Add "3", Now() & vbTab & "[SMS ID:" & smsID_ & "] Log file is exceeding the maximum file size allowed:" & logMaxSize & " Bytes. Archiving the current log file: " & logFile
MoveLogFiles()
fs.CreateTextFile logFile
logDic.Add "4", Now() & vbTab & "[SMS ID:" & smsID_ & "] Log file was archived: " & logTemp
End if
set f=nothing
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Write to the log file
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Application.Lock
dim log, logDicItems
Set log = fs.OpenTextFile(logFile, 8, True) '1=ForReading, 2=ForWriting, 8=ForAppending
If logDic.Exists("1") Then log.WriteLine logDic.Item("1")
If logDic.Exists("2") Then log.WriteLine logDic.Item("2")
If logDic.Exists("3") Then log.WriteLine logDic.Item("3")
If logDic.Exists("4") Then log.WriteLine logDic.Item("4")
log.WriteLine Now() & vbTab & psMessage
log.Close
Application.UnLock
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Set log = Nothing
fs.Close()
Set fs = Nothing
logDic.RemoveAll
Set logDic = Nothing
WriteLog = True
End Function
Function MoveLogFiles()
Dim fs: Set fs = Server.CreateObject("Scripting.FileSystemObject")
For i = logMaxArchives To 1 Step -1
if fs.FileExists(logFile & "." & CStr(i)) Then
if i = logMaxArchives Then
fs.DeleteFile logDirectory & logFilesDic.Item(logMaxArchives)
Else
fs.MoveFile logDirectory & logFilesDic.Item(i), logDirectory & logFilesDic.Item(i+1)
End if
End if
Next
fs.MoveFile logDirectory & logFilesDic.Item(0), logDirectory & logFilesDic.Item(1)
fs.Close()
End Function
' Generate unique identifier for SMS
Function CreateGUID(tmpLength)
Application.Lock
if tmpLength >= 64 or tmpLength < 0 Then
WriteLog "Error when generating SMS ID. Maximum length of characters allowed: 64. Value given: " & tmpLength
Elseif tmpLength < 4 Then
WriteLog "Error when generating SMS ID. Minimum length of characters allowed: 4. Value given: " & tmpLength
Else
Randomize Timer
Dim tmpCounter,tmpGUID
Const strValid = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
For tmpCounter = 1 To tmpLength
tmpGUID = tmpGUID & Mid(strValid, Int(Rnd(1) * Len(strValid)) + 1, 1)
Next
CreateGUID = tmpGUID
End if
Application.UnLock
End Function
Eventually the problem was caused by the Randomize Timer. Instead I used this:
Function CreateGUID()
Dim TypeLib: Set TypeLib = CreateObject("Scriptlet.TypeLib")
CreateGUID = TypeLib.Guid
CreateGUID = Left(CreateGUID, Len(CreateGUID)-3)
CreateGUID = Mid(CreateGUID,2)
Response.Write CreateGUID
End Function

How can I reference a dynamically created ID in HTA (vbscript)?

See slimmed down code. I'm essentially creating a list of items (printers) along with a dynamically created unique radio button ID, and then I'd like to be able reference said Radio ID in order to toggle the Checked between True/False in Sub SetDefaultPrinter. Why? Because using Add Devices / Search is too hard for some of our users, hence, a cute little GUI. Why dynamic? Because I have multiple separate networks and I'd prefer the script to adjust itself as needed.
<html>
<head>
<title>My HTML application</title>
<HTA:APPLICATION
APPLICATIONNAME="My HTML application"
ID="MyHTMLapplication"
VERSION="1.0"/>
</head>
<script language="VBScript">
Public jj, strPrinters, strModels, strLocations
Sub Window_OnLoad
strPrinters = Array("Printer1", "Printer2")
strModels = Array("HP Color LaserJet 4525", "HP Color LaserJet 4525")
strLocations = Array("Room 1", "Room 2")
jj = UBound(strPrinters)
Call OnClickGo()
End Sub
Sub OnClickGo()
DataArea1.InnerHTML = ""
For i = 0 To jj
DataArea1.InnerHTML = DataArea1.InnerHTML & "<BR><font style=color:green;font-weight=bold;>" &_
"<input type=""" & "radio""" & " name=""" &_
strPrinters(i) & "Radio""" & " id=""" & "Radio" & i & """" &_
" title=""" & "Clicking here will set " & strPrinters(i) & " as default printer.""" &_
" onclick=""" & "SetDefaultPrinter(" & i & ")""" & " onmouseover=""" & "Pointer""" &_
" onmouseout=""" & "DefaultCursor""" & "></input>" &_
"<span id=""" & strPrinters(i) & "Span""" &_
" title=""" & "Click here delete printer mapping for " & strPrinters(i) & """" &_
" onmouseover=""" & "Pointer""" & " onmouseout=""" & "DefaultCursor""" &_
" onclick=""" & "OnClickDelete(" & i & ")""" &_
">" & strPrinters(i) & ", " & strModels(i) & ", Location: " & strLocations(i) & "</span></font>"
Next
End Sub
'========================================
'= Set Default Printer ==================
'========================================
Sub SetDefaultPrinter(ii)
DataArea2.InnerHTML = strPrinters(ii) & " would have been set as default if this was fully functional."
'
' Radio0 and Radio1 are dynamically created IDs, *really* want to somehow
' dynamically reference the dynamically created IDs.
' i.e. something like
' If ii <> 0 Then (Radio & ii).checked = False
'
If ii <> 0 Then Radio0.checked = False
If ii <> 1 Then Radio1.checked = False
End Sub
'========================================
'= Delete Printer Mapping ===============
'========================================
Sub OnClickDelete(ii)
DataArea2.InnerHTML = strPrinters(ii) & " would have been deleted if this was fully functional."
'Set wshnetwork = CreateObject("WScript.Network")
'wshnetwork.RemovePrinterConnection "\\SERVER\" & strPrinters(PrinterToDelete)
End Sub
'========================================
'= MOUSE Pointers =======================
'========================================
Sub Pointer
document.body.style.cursor = "hand"
End Sub
Sub DefaultCursor
document.body.style.cursor = "default"
End Sub
</script>
<body bgcolor="white">
<span id="DataArea1"></span>
<BR><BR><BR>
<span id="DataArea2"></span>
</body>
</html>
user2345916, I have modified your code where the variables pass like you wanted. I left your comments intact, so you can pick up where you left off. Hope this helps!
Basically, the answer to your problem lies within the button's "ID", "VALUE" and "ONCLICK" values.
The ONCLICK='SetDefaultPrinter(" & i & ")' will pass the looped number to the SubRoutine.
The SetDefaultPrinter(Radioii) sets a variable from the "ONCLICK" field of the button that sends you to that SubRoutine (In this case, it's a 0 or 1).
The "FileName = document.getElementById("Radio" & Radioii).value" gets the "VALUE" field of the button that matches the "ID" field that is set between the "()", which in your case is also the variable that was pulled from the ONCLICK.
From here, you can use (FileName) variable to do whatever you want (Match IF/THEN, etc)
<script language=vbscript>
Sub Window_OnLoad
window.resizeTo 500,300
strPrinters = Array("Printer 1", "Printer 2")
strModels = Array("HP Color LaserJet 4525", "HP Color LaserJet 4525")
strLocations = Array("Room 1", "Room 2")
jj = UBound(strPrinters)
For i = 0 To jj
strHTML1 = "<span id='Delete" & i & "' value='" & strPrinters(i) & "'title='Click here delete printer mapping for " & strPrinters(i) & "' onmouseover='Pointer' onmouseout='DefaultCursor' onclick='OnClickDelete(" & i & ")'> " & strPrinters(i) & " - " & strModels(i) & ", Location: " & strLocations(i) & "</span>"
strHTML2 = strHTML2 & "<input type='radio' name='radio' value='" & strPrinters(i) & "' id='Radio" & i & "' title='Clicking here will set " & strPrinters(i) & " as default printer.' onclick='SetDefaultPrinter(" & i & ")' onmouseover='Pointer' onmouseout='DefaultCursor'>" &_
"" & strHTML1 & "</input><br>"
DataArea1.InnerHTML = strHTML2
Next
End Sub
'========================================
'= Set Default Printer ==================
'========================================
Sub SetDefaultPrinter(Radioii)
FileName = document.getElementById("Radio" & Radioii).value
DataArea3.InnerHTML = Filename & " would have been set as default if this was fully functional."
'
' Radio0 and Radio1 are dynamically created IDs, *really* want to somehow
' dynamically reference the dynamically created IDs.
' i.e. something like
' If ii <> 0 Then (Radio & ii).checked = False
'
If Radioii = 0 Then Radio0 = False
If Radioii = 1 Then Radio1 = False
End Sub
'========================================
'= Delete Printer Mapping ===============
'========================================
Sub OnClickDelete(Deleteii)
RemoveName = document.getElementById("Delete" & Deleteii).value
DataArea3.InnerHTML = RemoveName & " would have been deleted if this was fully functional."
'Set wshnetwork = CreateObject("WScript.Network")
'wshnetwork.RemovePrinterConnection "\\SERVER\" & strPrinters(PrinterToDelete)
End Sub
'========================================
'= MOUSE Pointers =======================
'========================================
Sub Pointer
document.body.style.cursor = "hand"
End Sub
Sub DefaultCursor
document.body.style.cursor = "default"
End Sub
</script>

Hide one radio button option on ASP Classic page

I asked a few month back how to hide a few drop down option on a Classic ASP page which were being pulled from a database so that users could not select those options. But now on one of the remaining options there appear 3 radio box options. I have to remove one of those options. The option which I need to remove is called value="_BML7(B)" according to Chrome.
The last time I inserted the following code into the following code into the include.asp file which worked great but that was to hide drop down options. This I need to hide one radio button option from the current drop down options.
Sub buildDropDownList(strCurrentSelection, objListData, strCodeName, strDescriptionName, blnIncludeOther)
If Not objListData.BOF Then
objListData.MoveFirst
End If
Dim currentCodeValue
While Not objListData.EOF
currentCodeValue = objListData(strCodeName)
If (UCase(currentCodeValue)<>"_04GIDBM") And _
(UCase(currentCodeValue)<>"_05GIDFM") And _
(UCase(currentCodeValue)<>"_03MIS(Q") And _
(UCase(currentCodeValue)<>"_06GIDMS") And _
(UCase(currentCodeValue)<>"_08EXHRM") And _
(UCase(currentCodeValue)<>"_10EXMKT") And _
(UCase(currentCodeValue)<>"_12EXTTH") And _
(UCase(currentCodeValue)<>"_15AFT") And _
(UCase(currentCodeValue)<>"_16HSC") And _
(UCase(currentCodeValue)<>"_18LTD") And _
(UCase(currentCodeValue)<>"_19EBM") And _
(UCase(currentCodeValue)<>"_17EXHSC") Then
Response.Write "<option value='" & currentCodeValue & "' "
If StrComp(strCurrentSelection, currentCodeValue, 1) = 0 then
Response.Write "selected"
End If
Response.Write ">" & objListData(strDescriptionName) & "</option>" & VbCrLf
End If
I could really use the help on this and thank everyone in advance for their help! I not very good with Classic ASP but I'm trying.
Here is the code that I inserted last time on the include.asp file.
<p align="center">
<%
do until rsProgramLevel.EOF
Response.Write "<input type=""radio"" name=""programcode"" onclick=""onProgramCode()"" "
Response.Write "value=""" & rsProgramLevel("ProgramCode") & """ "
if rsProgramLevel("ProgramCode") = strProgramCode then
Response.Write "checked"
end if
Response.Write ">"
Response.Write " "
Response.Write rsProgramLevel("LevelDescription") & " (£" & FormatNumber(rsProgramLevel("ChargeValue"), 2) & ") "
Response.Write " "
rsProgramLevel.MoveNext
loop
%>
</p>
You could compile the list into a string, like so...
Const ignoreCodes = " _04GIDBM _05GIDFM _03MIS(Q _06GIDMS _08EXHRM _10EXMKT _12EXTTH _15AFT _16HSC _18LTD _19EBM _17EXHSC "
Add it to the very top of your file (after any Option Explicit commands). If you have new codes to add to it simply ensure that there's a space either side of it.
Then just test against it...
If Instr(ignoreCodes, UCase(currentCodeValue)) = 0 Then
Response.Write("<option value='" & currentCodeValue & "' ")
If StrComp(strCurrentSelection, " " & currentCodeValue & " ", 1) = 0 then
Response.Write " selected "
End If
Response.Write(">" & objListData(strDescriptionName) & "</option>")
End If
If you think about this further, then simply include the list in a redundant codes table in a database.
To make this simple, just wrap the code sending the HTML with a basic If..Then statement:
Dim currentCode
do until rsProgramLevel.EOF
currentCode = rsProgramLevel("ProgramCode")
If UCase(currentCode)<>"_BML7(B)" Then
Response.Write "<input type=""radio"" name=""programcode"" onclick=""onProgramCode()"" "
Response.Write "value=""" & currentCode & """ "
if rsProgramLevel("ProgramCode") = strProgramCode then
Response.Write "checked"
end if
Response.Write ">"
Response.Write " "
Response.Write rsProgramLevel("LevelDescription") & " (£" & FormatNumber(rsProgramLevel("ChargeValue"), 2) & ") "
Response.Write " "
End If
rsProgramLevel.MoveNext
loop

Converting VBscript to VB Error (checking for right characters)

The following code was written in vbscript and I'm in the process of converting over to visual basic.
On the following line: If Right(LCase(oFile.Name), 3) = "pdf" Then I get the following error: Variable 'Right' is used before it has been assigned a value. A null reference exception could result at runtime. Also is says Object variable or With block variable not set.
To my best of knowledge, I believe it is checking to make sure the filenames right 3 characters are "pdf"?
For Each oFile In oFolder.Files
If Right(LCase(oFile.Name), 3) = "pdf" Then
Data = Replace(oFile.name, ".pdf", "")
Data = Replace(oFile.name, ".PDF", "")
Data = Split(Data, "-")
acct = Data(1)
lob = Data(2)
fileName = clientid & "-" & acct & "-" & lob & "-" & speciesid & "-" & seq & ".pdf"
outputLine = acct & "," & speciesid & "," & lob & "," & oFile.Name & "," & inputDate
oOutFile.WriteLine(outputLine)
End If
Next
You need to put:
Imports Microsoft.VisualBasic
at the beginning of your program. "Right" is a function in this namespace.
http://msdn.microsoft.com/en-us/library/dxs6hz0a(v=vs.80).aspx

HTA(vbs) - To do list - delete or modify array items

I'm trying to create an HTA To Do List saving locally to a text file. Every time you press submit button generates a new entry that display inside hta body and it's being saved inside the text file. I want to develop this furthermore :
delete an entry and update body/text file
modify an entry and update body/text file
put new entry on top
Any suggestions?
<html>
<head>
<HTA:APPLICATION SINGLEINSTANCE="yes" APPLICATIONNAME="To Do List">
</head>
<SCRIPT Language="VBScript">
Sub Window_OnLoad
ReadBlog
End Sub
Sub SaveData
strDel1="<"
strDel2=">"
Set objFSO = CreateObject("Scripting.FileSystemObject")
If objFSO.FileExists("C:\Test.txt") Then
Set objFile = objFSO.OpenTextFile("C:\Test.txt", 8)
strLine = strDel1 & Time & vbTab & Date & vbTab & Title.Value & vbTab & Message.Value & strDel2
objFile.WriteLine strLine
objFile.Close
Else
Set objFile = objFSO.CreateTextFile("C:\Test.txt")
strLine = strDel1 & Time & vbTab & Date & vbTab & Title.Value & vbTab & Message.Value & strDel2
objFile.WriteLine strLine
objFile.Close
End If
ReadBlog
ClearText
End Sub
Sub ReadBlog
Const ForReading = 1, ForWriting = 2
dim sampletext, objRegExp, SearchPattern, ReplacePattern, matches
Dim objFSO
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile("C:\Test.txt", ForReading)
Do Until objFile.AtEndOfStream
sampletext = objFile.ReadAll
SearchPattern = "<"
SearchPattern = SearchPattern & "(.*?)([\s\S]*?)"
SearchPattern = SearchPattern & ">"
Set objRegExp = New RegExp
objRegExp.Pattern = searchpattern ' apply the search pattern
objRegExp.Global = True ' match all instances if the serach pattern
objRegExp.IgnoreCase = True ' ignore case
Set matches = objRegExp.execute(sampletext)
If matches.Count > 0 Then ' there was at least one match to the search pattern
i=0
For Each match in matches
arrEntry = Split(Split(match.Value, "<")(1), ">")(0)
arrFields = Split(arrEntry, vbTab)
strTime = arrFields(0)
strDate = arrFields(1)
strTitle = arrFields(2)
strMessage = arrFields(3)
strHTML = strHTML & "<p>" & strTime & "</p>"
strHTML = strHTML & "<p>" & strDate & "</p>"
strHTML = strHTML & "<p>" & strTitle & "</p>"
strHTML = strHTML & "<p>" & strMessage & "</p>"
strHTML = strHTML & "<input type='button' name='Delete' value='Delete' >"& i &"<p>"
i=i+1
Next
Else ' there were no matches found
MsgBox objRegExp.Pattern & "was not found in the string"
End If
Loop
DataArea.InnerHTML = strHTML
Set objRegExp = Nothing
Set objFSO = Nothing
End Sub
Sub ClearText
Title.Value = ""
Message.Value = ""
End Sub
</SCRIPT>
<body>
<input type="text" name="Title" size="101"><p>
<textarea rows="10" cols="76" type="text" name="Message" size="25"></textarea><p>
<input type="button" value="Submit" onClick="SaveData">
<p><div id="DataArea"></div></p>
</body>
</html>
Are you particularly tied to using text files? If you used a database (such as access) you could do this quite easily (you don't have to have access installed to use an access database with an HTA either). And it would open up some other possibilities.
Incidentally, I also notice you're doing this:
strHTML = strHTML & "<p>" & strTime & "</p>"
strHTML = strHTML & "<p>" & strDate & "</p>"
strHTML = strHTML & "<p>" & strTitle & "</p>"
strHTML = strHTML & "<p>" & strMessage & "</p>"
Not a big thing, but concatenating the strings like that isn't great for performance. You'd be better off writing it all to the variable at the same time, otherwise it has to keep writing the variable to memory over and over again.
If you want to read a file with HTA you can easily do it in javaScript. Since the context changes IE allws you to directly read file on the computer or the network to wich the computer is linked to. In order to do so, you need to access the File System Object (FSO)
Full Documentation on FSO
If you are still looking to access a database you need to use the ADODB.Connection. That will allow you to connect to database localy or remotely. Altought there is not much documentation on the subject we did it at my work place. With a little imagination you can figure out how to fix it.
Documentation on the ADODB.Connnect
In this documentation the example are in VB but you can write them in JS as well.

Resources