I wrote this as a tutorial for Cogntive Science masters students in a programming course. I borrowed some text from a tutorial I found on the web about Visual Basic and HTA but rewrote it extensively for its lacunes and my main purpose: discussing the creation, saving, reading and writing from and to text files in general, and from within web pages specifically. It is instructive also for the use of COM objects from within html files/HTA's (including the Excel-COM that can be used to incorporate an Excel sheet in your HTA application). I hope you get excited.

If you have any comments or suggestions or other remarks, please e-mail me: rgrasman•{at}•uva•nl. Please forgive me for some of the crap (get on with it!), I will edit it when I have more time.


Back other HTA issues

HTML Applications Introduction

In the 'good' old days, when RAM was measured in bytes rather than megabytes, and processor speeds were measured in single figures, most operating systems came with a programming language. DOS had GWBASIC and QBasic, UNIX had it's shell scripting, most microcomputers used BASIC and CP/M relied on assembler. This gave users access to a programming language without the need to spend money. Magazines could publish program listings secure in the knowledge that users had access to the relevent language because it was bundled with the Operating System. Then along came the GUI (Graphical User Interface) and suddenly the facility dried up. QBasic was still shipped with Windows but it wasn't updated to take advantage of the new GUI so nobody used it (even though it is still a great way to get into programming). This has lead to a fragmentation of the number of languages that users could be using (Java, VB etc...). I believe this has lead to most users not being able to write even the most rudimentary programs. It could be argued that such skills are not required and that the GUI does it all for them. Sadly, this is just not true. There are many tasks that benefit from programming skills which the GUI does not encourage.

Then Microsoft came up with the Windows Scripting Host. It could be easily programmed in JScript (a version of JavaScript) using a text editor and it gave the user access to virtually all the facilities that could be found in full languages like C++. It is relatively slow because it is interpreted but that may be considered an advantage, as there is no need to mess around with compilers, and has much in common with the UNIX shell script. However, it lacked one vital ingredient. It's GUI features were limited to message boxes and input boxes which limited it's appeal. It is possible to write small applications with it but the graphical user interface (GUI) is very sparse.

Then along came Internet Explorer 5 and with it the HTA (HTML Application) which allowed scripts to be hosted inside IE complete with GUI widgets (like buttons, input fields, file selectors) but without the limitations imposed by the browser. HTA's look just like ordinary windows and can be run just like programs but they can also host HTML pages complete with graphics and all the active content that comes with it.

Surprisingly, for a technology so useful, there seems to be little mention of it in the computer press. Some examples of what you can achieve with HTA's can be found here (famous HTMLEditor sample at msdn.microsoft.com) and here (a little program I made).

Warning

Even though you will be programming in the relatively protected environment of the browser, it is still possible to crash or lock the computer which may require a reboot. I cannot accept any responsibility for damage of any kind arising from the use, misuse or modification of these programs and assumes no responsibilty for the correctness of the documentation or the correct functioning of the scripts. A full system backup should be carried out to a suitable medium before attempting to use any of these programs and tested on non-critical systems prior to use on essential systems


HTML Applications Tutorial

To follow this tutorial, you will need access to a Windows PC running Internet Explorer 5.0 or above. It will be necessary to construct a basic template file to make creating new files so much easier. This file will look something like this:-

<html> <head> <HTA:APPLICATION> <script type="text/javascript"> /* script goes here... */ </script> </head> <body> </body> </html>

You will notice that it is an HTML file despite the fact that a HTA is run locally and not on the web. Even though a HTA acts like an ordinary Windows program, it is actually still being run in a browser window albeit a specialised one. This allows us to use all of the active content and GUI widgets you associate with the web without actually having to run it over a connection or via a local web server.

Notice the line

<HTA:APPLICATION> This is the important bit. If you leave out this tag then some things such as message boxes will refuse to work with the file named with an extension of .hta but will work in an ordinary browser window with a .html extension.

Cut and paste this code into a file and name it template.hta. Double click on it and check there are no errors and that a window is displayed. If you make a copy of it and name it template.htm and remove the tag:-

<HTA:APPLICATION> then it will run in a standard browser window. The advantage of using .hta is that no security messages will be displayed once we start adding code which we will do now. Make a copy of template.hta and rename it to alertbox.hta. Between the two code tags add:- alert("Hello"); Save it and run it. Click OK. Note that the window remains. Pressing F5 will refresh it and run the program again. Click OK and close the window in the normal way. Congratulations. You have written your first HTA.

Writing to and Reading from Files

In any useful application, results are computed that you usually want to store more permanent than in the main memory. Maybe you want to analyze the data you have collected or created or computed later, or you want to transfer the data to another computer. In any case you want the data to persist, even if your computer is turned off. What you will want to do is write to and read from files. These will be stored on the local drive NOT on the Internet and can therefore be regarded as safe (or at least as safe as any other file created by an application). Consider the following program and cut and paste it into your template file.

var a, b, fs; var filename; filename = "hello.txt"; fs = new ActiveXObject("Scripting.FileSystemObject"); b = fs.CreateTextFile(filename, true); b.Close(); alert("Created"); When run, this will create a file called hello.txt in the same directory as the HTA which contains nothing at all. Here's how it works. First create a few temporary variables that will hold references to objects. var a, b, fs; Now we need a variable to hold a filename. var filename; filename = "hello.txt"; First, we create an object that knows how to deal with the file system. Don't worry too much about objects. You've doubtless come across the word before and been completely put off by the kind of language used to describe them. Forget all that. An object contains programs called methods that can do useful things for you and makes getting to the methods easier. That's it in a nutshell (the more knowledgeable amongst you will be tutting by now - I've simplified okay?). fs = new ActiveXObject("Scripting.FileSystemObject"); Now we have a reference to the filesystem object, one of the methods contained within it is to create a file. The next line will create the file with the filename we've used above. b = fs.CreateTextFile(filename, true); And then we close the file because we don't intend to write anything to it. Yet. b.Close(); Next, a message to the user just to confirm that something happened: alert("Created");

The file having been created can now be written to, which is what the next program does.


Start a new template file and cut and paste this into it.

ForAppending = 8; We will use this variable as a mnemonic for a number (the number 8, so chosen by Microsoft), with which we can tell the file system object that we want to add to the existing file. We setup some variables as before. var a, fs; var filename; filename = "hello.txt"; As before, we need a reference to the file system object. fs = new ActiveXObject("Scripting.FileSystemObject"); And now, we use the open text file method to open a file to be added to rather than overwritten. a = fs.OpenTextFile(filename, ForAppending); And now we want to write something to it. This is done in a very similar way as in document.write("bla ... "); statements. Here however we invoke a write command on a file (referenced by a) instead of on the document: a.Write("bla ... "); The WriteLine method adds a carriage return and linefeed to the end of its argument. When this file is opened in Notepad then it will display each character on two seperate lines: a.WriteLine("a"); a.WriteLine("b"); Close the file because we've finished. Failure to close a file may result in the file remaining empty or becoming corrupted. a.Close(); alert("Written"); Running this application more than once will merely append the same letters to the file making it larger and larger. Running the creation program will create a new version that will be empty again.

So now to read from the file you've created. Some variables and a reference to the filesystem as before.

ForReading = 1; ForWriting = 2; var a, fs; var retstring = ""; fs = new ActiveXObject("Scripting.FileSystemObject"); The file is opened. a = fs.OpenTextFile("hello.txt", ForReading); Now comes a loop. The program will keep going through the file until it reaches the end displaying each line in a message box as it goes. The file is then closed as usual. while(!a.AtEndOfStream){ retstring = retstring + a.ReadLine(); } a.Close(); alert(retstring); This time, provided the file has been created then this will read in the first line then the second then repeat until the end of the file has been reached.

Basically, this is all there is to it. In what follows we will delve into what has been presented so far in the next couple of sections a little bit more deeply.

Excercise HTA1
  Try changing the programs to create different files and try complete words and sentences to see how this might be useful in creating a simple database program.

HTA-tag revisited

It is at this juncture let's take a breather from the coding and consider what makes HTML Applications so special. When an ordinary web page is launched, it opens up in Internet Explorer complete with with all the buttons and security features that are essential for surfing the Internet. What Microsoft have done is taken the core of Internet Explorer (the bit that handles scripting) and made it look like an ordinary program. Why? Because it enables scripts to be run that are not reliant on the presence of the Internet so the various security features can be switched off making scripts run much more seamlessly, and to all intents and purposes are Windows programs that can be launched from shortcuts and menu's just like real programs. They even look like real programs, complete with icons and menu's. But they can also make use of all of the features we associate with a web browser such as graphics and hyperlinks (hyperlinks are launched in IE proper so security is preserved).

To make HTML Applications look even more like programs, the window containing the script can be controllled in certain specific ways. Here I am concerned with making them look more like ordinary Windows programs but there are other options that can be employed but these will not be gone into in any depth here. So, below is a HTML Application that does nothing but it does contain all the controlling code so we can test it all much more easily. The code is below. Don't be put off as I will explain it all further down.

<html> <head> <title>test</title> <HTA:APPLICATION ID="Test" ICON="http://users.fmg.uva.nl/rgrasman/programming/test.ico" SHOWINTASKBAR="yes" SINGLEINSTANCE="yes" SYSMENU="yes" WINDOWSTATE="normal" MAXIMIZEBUTTON="no" MINIMIZEBUTTON="yes"> <script type="text/javascript"> window.resizeTo(200,150); // resize the current window // to 200 pixels wide and 150 high </script> </head> <body scroll="no"> <!-- your content here --> </body> </html> So what does it all mean? Lets go through it a line at a time. Test This is the now familiar (I hope) beginning which is just standard HTML. <HTA:APPLICATION ID="Test" The opening < is important and must not be ommitted. There is a closing > (right sharp bracket) lower down. Here we specify that this is an HTA which makes it different from a standard web page. We also give this HTA a name and I have chosen to call it a (with little or no imagination) Test. APPLICATIONNAME="Test" We also now can give this application a name. The Application ID refers to the entire file and can be used to identify elements within the page. The Application Name is merely an identifier and the two need not be the same. BORDER="thick" This refers to the size of border which for a standard Windows app is set to thick. CAPTION="yes" The caption is the title that appears at the top of the window and although it can be switched off, it means that users don't have access to all the usual Windows style controls they are used to. ICON="test.ico" You can even assign an icon which will be displayed in the usual top left hand corner in the caption. This icon is a standard Windows icon and must be placed in the same folder as the .hta file or a full path can be specified although this makes the app less portable to other parts of the users hard drive. SHOWINTASKBAR="yes" It is possible to prevent the HTML Application from appearing in the task bar which may or may not be good thing depending on the application but it is neverless a very useful addition to the programmers armoury. SINGLEINSTANCE="yes" It is possible to prevent users from launching more than one version of the script. This is useful if a database application has been written and stops users overwriting with old data because they inadvertently have two versions of the app running. SYSMENU="yes" This enables the menu that is displayed when the icon in the caption is clicked (just like any other Windows app) and is the kind of control normally only available to Visual Basic programmers. You get the option for free! WINDOWSTATE="normal" Can be minimized or maximized when launched (not to be confused with the options below). MAXIMIZEBUTTON="no" This prevents the user from resizing the window by greying out the middle button in the top right hand corner of the window caption. Disabling this means that you don't have to add a whole lot of code to reposition all of the controls (buttons, text boxes etc..) when the window is maximised or set back to normal. MINIMIZEBUTTON="yes"> This allows the window to be minimized and can be reactivated by the user clicking on the relevent part of the taskbar. Note the closing > right sharp bracket. That completes the window definitions. Now we can start on the scripting sections as before. <script type="text/javascript"> Now this is something that shouldn't be unfamiliar. The next line, window.resizeTo(200,150); however, introduces the as to yet not encountered function resizeTo, of which you may guess what it does. <body scroll="no">

And thats just about it. The one other option that is sometimes useful is to switch off scrolling, which is done by setting the scroll attribute to "no". This means that none of the scroll bars that you normally get with web pages will appear making it look more like a real Windows application. However, it is essential to ensure that the window is the right size for its content when launched otherwise the user won't be able to scroll around to see all of the content.

You can find out more about the available attributes to the <HTA:APPLICATION> element, which make it more similar to Windows applications you encounter in the online reference.


Saving data to file

We are now getting into saving data to a file. This is something that you normally wouldn't be able to do in ordinary web pages whilst on the Internet. With HTML Applications however (that is, files with a .hta filename extension and a <HTA:APPLICATION> tag in the head of the HTML document), all security is switched off so we are free to save to a file on the local hard drive which almost all useful applications will want to do at some point. Here we are creating a file from scratch. If you try and run it twice, the file will be overwritten. <html> <body> <head> <title>Saving data</title> <HTA:APPLICATION> <script type="text/javascript"> function writeFile() // assumes: this file is a HTML Application // action: creates a text file called "hello.txt" and write the string // "Hello" to it { var b, fs; fs = new ActiveXObject("Scripting.FileSystemObject"); b = fs.CreateTextFile("hello.txt", true); b.WriteLine("Hello"); b.Close(); } </script> </head> <body scroll="no"> <input type="submit" id="btnQuit" value="Quit App" onclick="window.close();" /> <input type="submit" id="Create" value="Create" onclick="writeFile();" /> </body> </html> And here is what it all means. Most is the same as usual up to the point where the function writeFile is defined: function writeFile() // assumes: this file is a HTML Application // action: creates a text file called "hello.txt" and write the string // "Hello" to it { var b, fs; The last line declares two local variables, to be used later on the function body. The next line, fs = new ActiveXObject("Scripting.FileSystemObject"); creates a new ActiveX Object of the "Scripting.FileSystemObject" type. An object is simply a collection of variables ('properties') and functions ('methods') that can do things for us. The document is an example of an object, as is an Array object; the document object has the property body which itself has the property innerText (e.g., document.body.innerText = "Hello, World!"), and also the method write (e.g., document.write("Hello, World!")), an Array object has a length property (e.g., ["man","child","horse"].length, equal to the number of elements in the array), and a sort method (e.g., ["a","c","b"].sort(), which--surprise, surprise--sorts the elements of the array). In this case the object is a File System Object. This is in fact a library, akin to the sort of library you have been creating in .js files, which is stored on your Windows computer. A File System Object gives you full access to the entire structure of the files and folders hierarchy on your harddisk, and allows you to create, delete, and overwrite files (as you have already seen) and folders.

[In the "system" folder of your Windows system--most likely the "C:\Windows\system\" folder, i.e. the folder called 'system' in the folder called 'windows' on you harddrive C--you will find a great many files with the ".dll" filename extension: these are libraries, dynamic link libraries to be a bit more precise; they are there for Windows applications to use and share. Among them are also .ocx files, which are similar libraries, called ActiveX Objects, which allows one program to incorporate the functionality of another. For instance, there exists an ActiveX Object that allows you to incorporate Excel sheets into your webpage.]

Different programs may use a given ActiveX Object (e.g. the File System Object) simultaneously, and to prevent clashes between programs, every time the ActiveX Object library is asked for by a program, Windows creates a new instance of the object. The keyword new commands the interpreter to create a new instance of an object. The variable fs is assigned the reference to the new File System Object, through which you now have access to the file system on the hard drive. To do so we use its CreateTextFile method:

b = fs.CreateTextFile("hello.txt", true); Now it gets slightly complicated. The CreateTextFile method actually physically creates a file by reserving part of your harddisk. It then returns a reference to a File Object, which again consists of a collection of properties (variables) and methods (functions). Because there can be only one file with this name at this portion of the disk, it is impossible to create multiple instances of t, and so we don't use the new keyword. It might take you a while to get your head around what these two lines of code is doing. We first create an object that happens to be the file system object, and stored a reference to it in fs. Using this reference, we can then get to the function that will create the file for us which in this case we have called "hello.txt" which will be written to the folder where the .hta file is stored. Next, we can write to the file, using the WriteLine method that File Objects possess: b.WriteLine("Hello"); Here we are using the reference b to get to the function that will write a line into the file object created above with the simple string "Hello". We need to close the file, so that an end-of-file marker is written to the harddrive---if we don't, Windows or other programs will not know where the end of the file is and continue reading beyond outside the part of the harddrive reserved for the file: b.Close(); Now its all downhill: the dynamic HTML should be familiar. More on the File System Object and File Object can be found in the JScript reference that can be downloaded from the msdn microsoft site

Reading Data from File

So, now we've created a file, it's time now to read it back again. Consider the following program: <html> <body> <head> <title>Read data from file</title> <HTA:APPLICATION> <script type="text/javascript"> ForReading = 1; // global variable for mnemonic use function loadFile() // ...useful commenting... { var a, fs; fs = new ActiveXObject("Scripting.FileSystemObject"); a = fs.OpenTextFile("hello.txt", ForReading); alert(a.ReadLine()); a.Close(); } </script> </head> <body scroll="no"> <input type="Submit" id="btnQuit" value="Quit App" onclick="window.close();"> <input type="Submit" id="Read" value="Read" onclick="loadFile();"> </body> </html> This is very similar to the previous. The code breaks down as follows: ForReading = 1 function loadFile() // ...useful commenting... { var fs, a; The variables fs and a are local to this function, and cannot be accessed by other functions or the main program.
Next, we obtain an new instance of the File System Object, and open a file for reading, and the first line is read (for sake of simplicity only one line is read), and displayed using an alert box: fs = new ActiveXObject("Scripting.FileSystemObject"); a = fs.OpenTextFile("hello.txt", ForReading); alert(a.ReadLine()); Again, we must close the file explicitely: a.Close();

Reading files requires you to be pedantic

The file "hello.txt" in the previous example may not exist. This will result in an error message. Therefore, one must be able to test whether a file exists or not. This can be done using the FileExists method of the File System Object: <html> <body> <head> <title>Exists</title> <HTA:APPLICATION> <script type="text/javascript"> function reportFileStatus() // ...again some useful comment... { var fs, msg; fs = new ActiveXObject("Scripting.FileSystemObject"); if(fs.FileExists("hello.txt")){ msg = "file exists."; } else{ msg = "file doesn't exist."; } alert(msg); } </script> </head> <body scroll="no"> <input type="submit" id="btnQuit" value="Quit App" onclick="window.close();"> <input type="submit" id="btnExist" value="Exist?" onclick="reportFileStatus();"> </body> </html> Now hopefully you'll have a good idea of what is going on here.

One has to be even more pedantic: Before you start reading using ReadLine() (or Read(n) which reads n characters, or ReadAll(), which reads all there is in the file), you must check if you are not at the end of the file--that is, you must test if you're not at the "end of file" or "end of stream" (eof) marker on the harddrive of the file, this was done in the first program with a.AtEndOfStream which is false if there are more unread characters in the file, and true when none is left.

To repeat: More on the File System Object and File Object can be found in the JScript reference that can be downloaded from the msdn microsoft site

Excercise HTA2
  Combine the files from this Reading Data section with the files from the previous section (Saving Data to file) to create a program that will only create a file if it doesn't exist, and only read from it if it exists. You'll have three buttons: Quit, Read and Create with the relevent routines in the code.
Excercise HTA3
  Extend the program from exercise HTA3, to include a textarea that the user can type into, and that saves the text typed into this textarea. Also, let the user provide a filename to which the data should be saved in an input type="text" field. If the file exists, the user should be prompted if he would like to overwrite the existing file, or if he wants to provide a new name. To this end, you can use the confirm---for instance call confirm("The file " + filename +" exists allready. Do you want to overwrite?"). The return value of confirm is a Boolean value: true if the user clicked the 'OK' button, false if the user clicked the 'Cancel' button. When pressing the Read button, it should read the entire content of the file, and display the result in the textarea.