Newsletters #10

Since Microsoft released Service Pack 2 (and other security patches) for Windows XP, Internet Explorer blocks active content in HTML files. Greg Gerber, one of my readers notified me about that trouble - thanks Greg. After investigating the problem, I found out, that the script within my lokal HTML form is threaded in IE as active content and will be blocked. A WSH script, that tries to use some procedures from the HTML form, will fail. As a consequence, my HTML form samples used within my sample scripts (published in my WSH books) won't work anymore. But I found a way to modify my form samples to make it compatible with IE 6 and Win XP SP. So let's talk about the details.

(c) Günter Born, http://www.borncity.de

Warning: The material submitted as a newsletter comes AS-IS without any warranty of any kind. In no event shall the author be liable for damages and losses of any kind. The material discussed herein is copyrighted by the author. You get a free right to use it. This newsletter may be distribute freely as long as: a) the text remains intact and unmodified, b) a reference to the WSH Bazaar www.borncity.de is given and c) the newsletter is not shipped with other commercial material. If you like to ship the newsletter with CD-ROMs etc. please ask. Permission will be granted in normal cases, but I like to know where my material goes into.

Solving the security problem in WSH forms

What's the beef? Well, WSH doesn't support a GUI. That's a bit nasty, because WScript.Echo, PopUp and VBScript MsgBox statements are not really comfortable to display more than simple results. And only VBScript provides a primitiv user input dialog (inputbox statement). JScript users simply doesn't have anything to read a user input.

People who are intending to write scripts providing a user interface are forced to use my ActiveX form solution published in my ActiveX sample page (disadvantage: we need to install the ocx-files on all target machines).

Or they can use a simple trick: Just launch a html document in Internet Explorer from a WSH script. If that html document contains a form, this form may be used for user input (a detailed discussion how to implement user forms may be obtained from my article Using Forms in VBScript/JScript). A small script within the html file provides a procedure, callable from the WSH script, to indicate that the user has clicked the OK button to close the form. The WSH script forces IE to load a html form. Then the script polls the form's procedure until a "ready flag" signals that the user wishes to close the form. After receiving this flag, the WSH script reads the user input from the forms input elements, closes the IE session and displays the results. Pretty cool, isn't it.

Unfortunately, security updates of IE and Win XP SP2 blocks active content in html documents. In consequence, after a WSH script forced IE to load a form, the script procedures within the form are not executed until the user allows IE to display active content. The WSH script fails to call a user defined procedure within the form.

Well, this pitfall can be solved using a html form that doesn't contain a script. All actions need to be implemented in WSH scripts. Let's have a look at a simple form.

The HTML code to implement this form will be shown below.

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Form input - by Günter Born</title>
</head>
<body bgcolor="#C0C0C0" scroll="no">
<h3>Form</h3>
<hr>
<form name="ValidForm">
 <p>Name: <input type="text" size="5" name="Text1">&nbsp; Age:
 <input type="text" size="3" name="Number">&nbsp; 
 <input type="button" name="Button1" value="OK"></p>
</form>
</body>
</html>

This HTML code is pretty simple - the trick is to assign a name attribut to each form element. This attribut may be used within a WSH script to access the element.

Now it's time to implement a WSH script that forces IE to load the form. Then the script shall wait until the user clicks the OK button. After detecting that mouse click, the script shall read the form's input data, closes the form and displays results. The following code sequence launches IE.

' *** launch Internet Explorer ***
Set oIE = WScript.CreateObject("InternetExplorer.Application")
  oIE.left=50             ' window position
  oIE.top = 100           ' and other properties
  oIE.height = 200
  oIE.width = 350
  oIE.menubar = 0         ' no menu
  oIE.toolbar = 0
  oIE.statusbar = 0
' commented out, because it causes a corrupted window  
  oIE.resizable = 0      ' disable resizing
  oIE.navigate path & "Form1.htm"  ' Form
  oIE.visible = 1         ' keep visible

' Important: wait till MSIE is ready
Do While (oIE.Busy)  
   WScript.Sleep 100   ' supend, just to lower CPU load   
Loop

After IE tells us that the form is loaded, the script needs to connect its event handler to the OnClick event of the form's OK button. This may be done using the following two VBScript statements:

' now connect the event handler
Set oBut = oIE.document.getElementById ("Button1")
Set oBut.onclick = GetRef ("GetFormValue")

The event handler, implemented within the script, contains just the code to read the form elements.

' ### Event handler ###
Sub GetFormValue
' User has clicked the OK button, get values
If test Then WScript.Echo "Event raised"
result1 = "Value1: " & oIE.Document.ValidForm.Text1.Value
result2 = "Value2: " & oIE.Document.ValidForm.Number.Value
ready = true ' set ready-flag
End Sub

An element within the form may be accessed using the path to the object like oIE.Document.ValidForm.Text1.Value. "Text1" is the object name assigned within the elements HTML tag using the name attribute. The last statement sets a flag ready to tell the script's main procedure, that the user already clicked the OK button. Then the main script may terminate the IE session using a oIE.Quit statement. Further details may be obtained from the following listing.

'************************************************
' File:    Form1b.vbs (WSH sample in VBScript) 
' Author:  Günter Born
'
' Uses Internet Explorer 6.0 for form input. Works
' also with Win XP SP2!
'************************************************
Option Explicit

Const test = false    ' set to false to disable Messages

Dim oIE      ' declare variables
Dim path
Dim Title
Dim Text2
Dim result1, result2
Dim oBut
Dim ready

Title = "WSH sample form input - by G. Born"
Text2 = "You entered:" & vbCRLF

' *** get script path -> because form (HTML file)
' *** must be in the same folder!!!
path = WScript.ScriptFullName
path = Left(path, InstrRev(path, "\"))

If test Then WScript.Echo "Script launched"

' *** launch Internet Explorer ***
Set oIE = WScript.CreateObject("InternetExplorer.Application")
  oIE.left=50             ' window position
  oIE.top = 100           ' and other properties
  oIE.height = 200
  oIE.width = 350
  oIE.menubar = 0         ' no menu
  oIE.toolbar = 0
  oIE.statusbar = 0
' commented out, because it causes a corrupted window  
  oIE.resizable = 0      ' disable resizing
  oIE.navigate path & "Form1.htm"  ' Form
  oIE.visible = 1         ' keep visible

If test Then WScript.Echo "Wait for IE"

' Important: wait till MSIE is ready
Do While (oIE.Busy)  
   WScript.Sleep 100   ' supend, just to lower CPU load   
Loop

If test Then WScript.Echo "Connect handler"

' now connect the event handler

Set oBut = oIE.document.getElementById ("Button1")
Set oBut.onclick = GetRef ("GetFormValue")


If test Then WScript.Echo "Wait, until user clicked OK"

'Wait until the OK button has clicked
ready = false
Do Until ready
  WScript.Sleep 100  ' supend, just to lower CPU load
Loop

' try to display the results
MsgBox Text2 & vbCRLF & result1 & vbCRLF & result2, _
        vbOKOnly + vbInformation, Title

oIE.Quit               ' close Internet Explorer
Set oIE = Nothing      ' reset object variable 


' ### Event handler ###
Sub GetFormValue
' User has clicked the OK button, get values
 If test Then WScript.Echo "Event raised"
 result1 = "Value1: " & oIE.Document.ValidForm.Text1.Value
 result2 = "Value2: " & oIE.Document.ValidForm.Number.Value
 ready = true  ' set ready-flag
End Sub
' End

The global variables result1 and result2 are used to pass the results obtained within the event handler to the main procedure. The ready flag tells whether the form may be closed or not. Using this technique, you may access any form's item from your WSH script. And this solution will run also in future IE security updates, because it just contains pure HTML code.

© by G. Born

Disclaimer

Use it at your own risk. Further information about WSH may be found in the WSH Bazaar at: www.borncity.de.

Planned topics for newsletter #11 and future newsletters:

Enyoy scripting, till the next newsletter arrives...


(c) G. Born, 14 - January 2005 (the day the Huygens probe will hit Titan) - www.borncity.de