Archive - HTA

"" - ""  
 



.Contents.
 
bar1
    

HTML Applications (HTAs) provide a way for you to wrap your scripts up in a graphical user interface, an interface replete with check boxes, radio buttons, drop-down lists and all those other Windows elements you’ve grown to love. In this article, the first of a multi-part series, we’ll introduce the basics behind
creating your very own HTA.


Creating Your Own HTAs

You might have noticed that you can’t buy MS-DOS any more, and for good reason: after people got a look at Windows, well, typing in long, cryptic commands from the C:\ prompt just didn’t seem like nearly as much fun. The command prompt still has its place, but the success of Windows (and the Macintosh, and all the new Windows-like Unix shells) suggests that most people prefer a graphical user interface.

Because of that you might expect the Microsoft scripting technologies - such as Windows Script Host (WSH) and VBScript - to have some of the coolest and fanciest graphical user widgets around. Oddly enough, though, that isn’t the case. Outside of a message box here and an input box there, neither WSH nor VBScript offers much in the way of GUI elements. Using WSH and/or VBScript, can you create a form that enables you to select computer names from a list box? No. Can you create a form that allows people to select options from a series of check boxes? No. Can you - sorry; no. If you want a graphical user interface, you’re simply going to have to give up scripting and turn to full-fledged, full-time programming.

Or are you? Let’s think about this for a second: why do people like scripting in the first place? Well, scripting enables you to perform useful tasks quickly and easily, without having to compile anything and without having to use anything more powerful (or expensive) than * Notepad. Suppose we told you that you could create a useful utility, like the following, quickly and easily, without having to compile anything and without having to use anything more powerful (or expensive) than * Notepad:

hta_1

Would that satisfy your craving for a graphical user interface? If so, then welcome to the world of HTAs.



What is an HTA?

The term HTA is actually an acronym: it’s short for HTML Application. For our purposes an HTA is nothing more than a way to provide a graphical user interface for your scripts. As we’ve already * Noted, neither WSH nor VBScript provide much in the way of graphical user interface elements: no check boxes, no list boxes, no nothing. Internet Explorer, however, makes use of all of these elements - and more. Because an HTA leverages Internet Explorer, you can take advantage of all these graphical user interface elements when writing system administration scripts. (And, yes, we’re going to show you how to do just that.)


How closely related are HTML files and HTAs? Well, take any HTML file and change the file extension from .htm (or .html) to .hta. Congratulations: you’ve just created your first HTA.


So Why Don’t I Just Use an HTML File?

There’s a very simple answer to that: security. There are a lot of security restrictions placed on Internet Explorer, and for good reason: if you visit a Web site you’d probably prefer that this Web site not use a client-side script that starts reconfiguring your settings or rooting around through your file system. Consequently many system administration scripts - including those that use WMI or ADSI - either will fail when run from Internet Explorer or, at best, will present you with a dialog box similar to this one:

hta_2


Any time you run your script from an HTML file you’ll be presented with a dialog box like this. That might be OK, but it’s definitely not the best possible user experience.

HTAs, by contrast, are not bound by the same security restrictions as Internet Explorer; that’s because HTAs run in a different process than Internet Explorer. (HTAs run in the Mshta.exe process rather than the Iexplore.exe process.) Unlike HTML pages, HTAs can run client-side scripts and they have access to the file system. Among other things, this means that HTAs can run your system administration scripts, including those that use WMI and ADSI. Your scripts will run just fine, and you won’t receive any warnings about items that might be unsafe.

Of course, this doesn’t mean that HTAs somehow bypass Windows security. For example, if you don’t have the right to change a user’s password then you can’t use a script to change a user’s password. Placing that script in an HTA won’t make a difference: you still won’t be able to change the user’s password. And HTAs do have some security restrictions of their own. We don’t want to get too bogged down in the details today, so let’s leave it at this:

·         Serverhough HTAs use Internet Explorer and the Internet Explorer object model, they run in a different process than Internet Explorer. Consequently, they can run scripts and perform other tasks that aren’t allowed in Internet Explorer.

·         If you’d like more information about HTAs and security, take a look at the HTML Applications SDK on MSDN. 



How Do I Create One of These HTA Things?

Boy, is this a coincidence or what: this article just happens to be the first in a series of tutorials that will teach you - that’s right - how to create your own HTA! (What do you suppose the odds were of that happening?) This month we’ll introduce the basics of HTA construction. In subsequent articles we’ll begin delving into more advanced topics. Should be fun, huh?

* Note. What do you mean, “A series of monthly articles takes too long; I want to master HTAs right now!” Well, that might be a bit of a problem. The truth is, there aren’t very many good resources out there for the beginning HTA writer.

However, you might check out the
HTA Helpomatic tool, which includes a number of code snippets that you can paste
into your HTA. And as you get a little better at HTA creation, check out
The ABCs of HTAs.

 

Speaking of basics, we should probably mention right off the bat that HTAs can be created using * Notepad or any other text editor. However, because of the heavy-duty use of HTML you might consider creating your HTAs in a Web page editor such as Microsoft FrontPage. Regardless, you create a plain text file and then save it with a .HTA file extension. A very rudimentary - but complete - HTA might look something like this:  

<head>
<title>HTA Test</title>
<HTA:APPLICATION 
     APPLICATIONNAME="HTA Test"
     SCROLL="yes"
     SINGLEINSTANCE="yes"
     WINDOWSTATE="maximize"
> 
</head>
 
<script language="VBScript">
    Sub TestSub
        Msgbox "Testing 1-2-3."
    End Sub
</script>
 
<body>
<input type="button" value="Run Script" name="run_button"  onClick=
"TestSub"><p> 
 
</body>
 



Don’t worry; it’s nowhere near as complicated as it might first appear. In fact, it’s possible to break an HTA down into three basic parts, each of which we’ll explain in some detail:

·         The <HTA:Application> tag

·         The </script> tag

·         The <body> tag


The <HTA:Application> Tag

You can actually create an HTA without using the <HTA:Application> tag; your HTA will run just fine and there will be no change in functionality or performance.

So if you don’t have to use the <HTA:Application> tag then why would you ever want to use it? (Hmmm, when you put it that way you sound remarkably like one of the teenage Scripting Sons.…) Well, the <HTA:Application> tag provides you with the ability to control the appearance of your HTA window; this is done by configuring the various tag properties. Here’s the <HTA:Application> tag used in our sample script:

 
<head>
<title>HTA Test</title>
 
<HTA:APPLICATION 
     APPLICATIONNAME="HTA Test"
     SCROLL="yes"
     SINGLEINSTANCE="yes"
     WINDOWSTATE="maximize"
> 
 
</head>
 

* Note. The <title> tag is actually separate from the <HTA:Application> tag; it simply refers to text that appears in the title bar of the HTA window. We show it here simply because the title is usually found inside the <head> tag, the same place we find <HTA:Application>.

 

What does this tag do? Well, the ApplicationName property sets the name of the HTA as shown in Windows Task Manager. If you don’t specify an application name, Task Manager displays the path to the HTA file. Setting the Scroll property to Yes causes scroll bars to automatically appear in the HTA if returned data is bigger than the window size; if set to No then only the data that actually fits in the window will be displayed. The SingleInstance property ensures that only one instance of your HTA will run at a time; clicking the HTA file icon will not start a second instance of your little application.

And let’s not forget WindowState: setting the WindowState to maximize causes the HTA to display in a full-sized window each time the HTA starts up.



Some of the more useful HTA Application properties are shown in the following table. For a complete list of properties see the HTML Applications SDK on MSDN.

Property

Description

ApplicationName

Sets the name of the HTA. This name is used to enforce the SingleInstance property, and is also the name that appears in Windows Task Manager.

Border

Sets the type of border used for the HTA window. Values include thick (for a resizable window) and thin (for a non-resizable window).


Caption


Yes/No value specifying whether the HTA displays a caption in the title bar. The default value is Yes.

MaximizeButton

Yes/No value specifying whether the HTA displays a Maximize button in the title bar. The default value is Yes.

MinimizeButton

Yes/No value specifying whether the HTA displays a Minimize button in the title bar. The default value is Yes.

Scroll

Yes/No value specifying whether the HTA will scroll if returned data is larger than the window size. The default value is Yes.

ShowInTaskbar

Yes/No value specifying whether the HTA is shown in the Windows taskbar. The default value is Yes.

SingleInstance

Yes/No value specifying whether more than one instance of this HTA can be active at a time. For this property to take effect, you must also specify an ApplicationName. The default value is Yes.

SysMenu

Yes/No value specifying whether the HTA displays the System menu in the title bar. The default value is Yes.

WindowState

Sets the initial size of the HTA window. Values are Normal, Minimize, and Maximize. By default the WindowState is set to Normal.

 



The following illustration maps some of these properties to an actual HTA window:

hta_3


The <script> Tag

Serverhough there are exceptions, many VBScript scripts (that is, .vbs files) do their thing and then get out of there; probably 99% of the scripts found in the Script Center Script Repository do just that. What do we mean when we say these scripts “do their thing and then get out of there?” Well, when you start most VBScript scripts the script host executes line 1, then - without missing a beat - executes line 2, then line 3, and so on. After the last line in the script has been executed, the script ends, the script host process terminates, and the party’s over.

By contrast, HTAs usually don’t work that way; that’s because HTAs are “event driven” applications. In general, when you start an HTA nothing happens; instead the HTA just sits there. In fact, the HTA will sit there forever until an event occurs that the HTA has been programmed to respond to. Typically that means someone clicked a button, selected an item from a drop-down list, or did something similar.

* Note. Could you create an HTA that automatically does something the moment you start it? Sure: just include your code inside a subroutine named Window_onLoad. As the name implies, that subroutine automatically runs any time the HTA window is loaded or refreshed. For example, this code automatically calls the TestSub subroutine each time you start your HTA: 

 
Sub Window_onLoad 
    TestSub 
End Sub
 

 

In other words, instead of being one big, long, continuous script designed to run from start to finish, an HTA is often composed of separate and distinct smaller scripts: there’s one script that runs any time a user clicks Button A, another script that runs any time a user clicks Button B, and so on. Does this have implications for the scripts we want to use in our HTA? You bet it does.

In fact, there are at least two implications. To begin with, all these separate and distinct scripts must be housed inside a single <script> tag; this, by the way, is standard HTML practice. Second, each “script” is actually a subroutine, one that needs to have a distinct name. (You can name a subroutine anything you want, as long as there are no spaces or other illegal characters in the name. For more information, see the Procedures section of the Microsoft Windows 2000 Scripting Guide.) From now on we’ll use the term subroutine to refer to these blocks of code; that should help differentiate the code we want to run from the <script> tag.

Here’s an example of a <script> tag that includes a single subroutine: TestSub. In a little bit we’ll explain how to add additional subroutines to this tag.
 

 
<script language="VBScript">
    Sub TestSub
        Msgbox "Test"
    End Sub
</script>
 


There’s nothing too complicated here: just remember that you need to place all your code in subroutines and all your subroutines must be inside the <script> tag.


OK, We Give Up. So if HTAs don’t run and then automatically terminate, how do you exit an HTA? Well, the easiest way
is probably just to click the window’s Close button. Of course, it’s possible to create an HTA that doesn’t have a Close button; for an example, see this article in the
ABCs of HTAs. In a case like that you can use a subroutine like this to exit an HTA: 

 
Sub ExitHTA
    self.close()
End Sub
 

 

The <body> Tag

If you’ve ever put together a Web page you know that the body of the document is where most of your “stuff” goes: your text, your tables, your buttons, your check boxes, your horizontal rules, etc. The same thing is true with an HTA. When you build an HTA you typically put the <HTA:Application> tag at the top followed by the <script> tag. Last - but definitely not least - comes the <body> tag. Inside the body tag will be the elements that you want to appear in your HTA’s user interface. In our sample HTA we have a very simple user interface; it consists of a single button labeled Run Script. As you can see, the HTML tagging for the button is included between the <body> and </body> tags:

 
<body>
<input type="button" value="Run Script" name="run_button"  onClick=
"TestSub"><p> 
 
</body>
 


To be honest, the <body> tag is kind of boring; what’s interesting are the
elements that go inside that tag. In this first article we’ll focus on two of these elements: buttons and spans. In subsequent articles we’ll cover additional things like check boxes, radio buttons, and list boxes.

My Very First HTA

We know what you’re thinking, “Yeah, yeah, Tech Guys: now when do we get to the good stuff?” Well, how about right now? Here’s a sample HTA that will tell you the version of the operating system installed on the local computer. To try this HTA out, copy the code, paste it into * Notepad, and the save the thing with a .hta file extension (for example, MyFirstHTA.hta). Then just double-click the file icon in My Computer or Windows Explorer and get ready for some excitement:

 

<head>
<title>Operating System Version</title>
<HTA:APPLICATION 
     APPLICATIONNAME="Operating System Version"
     SCROLL="yes"
     SINGLEINSTANCE="yes"
> 
</head>
 
<script language="VBScript">
 
    Sub GetOSVersion
       strComputer = "."
           Set objWMIService = GetObject("winmgmts:\\" & strComputer
 &  "\root\cimv2")
 
           Set colOperatingSystems = objWMIService.ExecQuery _
               ("Select * from Win32_OperatingSystem")
 
           For Each objOperatingSystem in colOperatingSystems
               Msgbox objOperatingSystem.Caption & " " & _
                   objOperatingSystem.Version
           Next
    End Sub
</script>
 
<body>
<input type="button" value="Operating System" name="run_button"  
onClick="GetOSVersion">
 
</body>
 


So what happens when you start the HTA and click the Operating System button? You should see a message box similar to this:

hta_4


Yes, we know; but you have to start somewhere, right? We’ll add a few additional features as time goes on. And don’t worry if you don’t understand what we did here. In just a moment, we’ll start walking you through all the relevant lines of code. But first, a quick * Note about HTA aesthetics.


Making Our HTA Prettier

We admit it: at the moment, our HTA has an appearance that only a mother could love. Can we make it a little prettier, but without having to work too terribly hard at that? Sure we can; after all, the body of the HTA is - at heart - just another HTML page. Therefore we can try making our HTA a little prettier by beefing up the <body> tag. For example, how about a nice cyan background:

hta_5


That’s right: eat your heart out, Paris Hilton. We can change the background color of our HTA just by adding a bgcolor attribute to the <body> tag. For example, this sets the background color to that breathtaking shade of cyan shown above: 

 
<body bgcolor="cyan">
 

There are plenty of other colors you can use besides cyan; for a list, take a look at the Internet Explorer documentation.

If you have a picture you find suitably attractive you can serverernatively set the background attribute to the name of that picture:

 

 
<body background = "keyboard.jpg">
 


Depending on what Keyboard.jpg looks like you’ll end up with something like this:

hta_6


Cool, huh? Keep in mind that depending on the color of your background you might also need to change the color of your fonts, something we’ll deal with later. And as long as we’re on the subject you might want to check out the gradient background explained in the ABCs of HTAs. That’s way cool, and has the advantage of not requiring a .JPG or other picture file.

Adding a Button

One feature almost every HTA ends up having is a good old-fashioned button. Your HTA might have fancy check boxes and list boxes and other items for configuring options and setting preferences, but at some point you’ll need to do something to tell the HTA to get to work. More often than not that will involve clicking a button.

Adding a button to an HTA is no different than adding a button to an HTML page. For example, this code adds a button labeled Operating System to our HTA:

 
<input type="button" value="Operating System" name="run_button" 
onClick="GetOSVersion">
 

As you can see, we use the <input> tag along with a number of attributes. Let’s take a quick look at those attributes and what they do:

Attribute

Description

Type

This specifies the type of <input> element to be placed on the page; as we’ll see next month the <input> tag can take on forms other than a button.


value


“Value” is a misleading term; what we’re really talking about here is the label that appears on the button. In other words, in this example we’re creating a button that has the label Operating System.

name

As you might expect, this is a unique name given to the button. Why give your button a name? Well, you don’t have to; you can leave this attribute out if you wish. However, if your buttons do have names then they can be configured and modified using scripts. For example, you can enable or disable buttons programmatically.

We’re getting a bit ahead of ourselves here, but this code disables a button named Run_Button:

 
Sub DisableButton
    Run_Button.Disabled = TRUE
End Sub
 

onClick

This is the name of the subroutine we want to run any time the button is clicked. This is optional; you can create buttons that don’t actually do anything when clicked. (And, no, buttons that don’t actually do anything are not known as Tech Guys Buttons. Though we suppose they could be….)


Incidentally, these are not the only attributes that can be configured for a button. For more information see the HTML and DHTML Reference on MSDN.

Learn By Doing. At the moment we have an HTA with a single button; click that button and the HTA will report back the version of Windows installed on the local machine. That’s probably not going to revolutionize the software industry, but it’s still a useful little utility. Now, suppose we also want to retrieve the version of the latest service pack installed on the computer. Furthermore, suppose we want this to be a separate script; that is, we want to be able to get the operating system version or the service pack version. How can we do that?

Well, we could create a second HTA, one that had a single button and performed a single task (retrieving the service pack version). Serverernatively, we could simply add a second button to our existing HTA, a button with the name service_pack and the label (value) Service Pack, which runs a subroutine named GetServicePack any time the button is clicked. (And, yes, we know that this subroutine doesn’t exist. But we’ll take care of that soon enough.) So here’s your assignment: see if you can add a second button to your HTA, and end up with something that looks like this:


hta_7



And, no, we’re not going to tell you the answer, at least not here. (But if you’re having problems figuring this out, click
here.) However, we will give you a hint: try copying and modifying the code for the existing button.

You’re right: we did sort of give it away, didn’t we?


Adding a Subroutine

Early in this article we showed you a very simplistic subroutine; now let’s take a look at a more practical example, the subroutine we used in our Operating System HTA. * Note that the code inside the subroutine is standard WMI code; with a few exceptions involving Windows Script Host (something we’ll discuss in a moment) almost any code that runs in a standalone .vbs script can run in an HTA. You might want to (or have to) make some changes to ensure that the output displays properly, but the basic code functions - connecting to the WMI service, running the ExecQuery method, looping through a collection of returned data - can be left as-is.

Here’s the sample subroutine. * Note that - like all subroutines - it’s housed between the <script> and </script> tags:

 
<script language="VBScript">
 
    Sub GetOSVersion
       strComputer = "."
           Set objWMIService = GetObject("winmgmts:\\" & strComputer
 &  "\root\cimv2")
 
           Set colOperatingSystems = objWMIService.ExecQuery _
               ("Select * from Win32_OperatingSystem")
 
           For Each objOperatingSystem in colOperatingSystems
               Msgbox objOperatingSystem.Caption & " " & _
                   objOperatingSystem.Version
           Next
    End Sub
 
</script>
 

What if we wanted to have a second subroutine, one that runs when we click a different button? That’s no problem; you can include as many subroutines as you want inside the <script> tag. Just make sure that you give each subroutine a unique name, and be sure and use the End Sub statement to mark the end of each subroutine. For example, here’s a very simple subroutine (named MySecondRoutine) that we’ve added to the <script> tag:

 
<script language="VBScript">
 
    Sub GetOSVersion
       strComputer = "."

   Set objWMIService = GetObject("winmgmts:\\" & strComputer &_  
"\root\cimv2")
 
           Set colOperatingSystems = objWMIService.ExecQuery _
               ("Select * from Win32_OperatingSystem")
 
           For Each objOperatingSystem in colOperatingSystems
               Msgbox objOperatingSystem.Caption & " " & _
                   objOperatingSystem.Version
           Next
    End Sub
 
    Sub MySecondRoutine
        Msgbox "This is my second subroutine."
    End Sub
 
</script>
 


Learn By Doing
.

If you did the previous Learn By Doing exercise you have a second button in your HTA interface, one that - in theory - retrieves the version of the latest service pack installed on the computer. Why do we say “in theory?” Because, at the moment, we have a button, but that button isn’t tied to a script that can retrieve the service pack version. So let’s see what we can do about that. Here’s a script that reports back the version of the latest service pack installed on the computer:

 

 
strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & _
"\root\cimv2")
 
Set colOperatingSystems = objWMIService.ExecQuery _
    ("Select * from Win32_OperatingSystem")
 
For Each objOperatingSystem in colOperatingSystems
    Msgbox objOperatingSystem.ServicePackMajorVersion  _
        & "." & objOperatingSystem.ServicePackMinorVersion
Next
 


See if you can take this code and add a subroutine named GetServicePack to your HTA. After you’ve added the subroutine, start the HTA, click the Service Pack button and verify that your new subroutine works.

 



Why Can’t I Use Wscript.Echo?

You might have noticed that when it came time to report back the operating system version we used the VBScript Msgbox function rather than the more common Wscript.Echo. Why didn’t we use Wscript.Echo? Here’s why:

hta_8


As it turns out the various Wscript methods - Wscript.Echo, Wscript.Sleep, Wscript.Quit, etc. - are designed solely to run under the Windows Script Host environment. When we’re working in an HTA we’re not running under WSH; instead we’re running under the MSHTA process. Because of that the Wscript methods are not available to us (nor can we create them). Consequently we need to find workarounds for each method, and Msgbox is a perfectly adequate replacement for Wscript.Echo. (We’ll talk about workarounds for other methods - such as Wscript.Sleep - when we get to them.)

The moral of the story: Don’t bother with Wscript.Echo; it won’t work.

Using a <span> Tag

So far our HTA works great: you click a button and you get back a message box with information about the operating system or the latest service pack installed on a computer. Very cool. Now, suppose we want to add the ability to retrieve a list of all the processes running on a computer. That’s easy enough, except for one thing: right now the computer being used to type this tutorial has 49 processes running on it. That’s a problem; who wants to respond to 49 message boxes, one for each process?

We’re not silly enough to say “nobody,” but we’ll go out on a limb and say that most people would rather not click OK 49 times. (47 or 48 maybe, but not 49.) So let’s see. We need to display data somewhere other than in a message box, and we have an HTA that has plenty of white space just sitting there doing nothing. Hmmm, that gives us an idea….

Did someone say, “Why don’t we just display the data in the HTA itself?” Good idea; in fact, way better than the idea we came up with. This is one of the real benefits of using an HTA: not only can you display data in your application itself but - as we’ll see - you can also display formatted data in that HTA. But how exactly do we do that?

Actually there are several different ways. The one we find the easiest to code involves the use of the <span> tag. The <span> tag enables you to name an area within your HTA and then programmatically manipulate all the HTML elements within that tag. What does that mean?

Well, save the following code as a .HTA file, run the thing, and then click the Operating System button:

 
<head>
<title>HTA Test</title>
<HTA:APPLICATION 
     APPLICATIONNAME="HTA Test"
     SCROLL="yes"
     SINGLEINSTANCE="yes"
> 
</head>
 
<script language="VBScript">
    Sub GetOSVersion
        strComputer = "."
        Set objWMIService = GetObject("winmgmts:\\" & strComputer &_
 "\root\cimv2")
 
        Set colOperatingSystems = objWMIService.ExecQuery _
            ("Select * from Win32_OperatingSystem")
 
        For Each objOperatingSystem in colOperatingSystems
            DataArea.InnerHTML = objOperatingSystem.Caption &_
 " " & objOperatingSystem.Version
        Next
 
    End Sub
</script>
 
<body>
<input type="button" value="Operating System" name="run_button" 
onClick="GetOSVersion">
<p>
<span id = "DataArea"></span>
</body>
 




Your screen should look something like this:

hta_9


See? No message box; instead our data is written to the HTA itself.

To accomplish this astonishing feat we didn’t have to sell our souls, we only had to do two things. First we modified the <body> area to include a <span> (and specified an id of DataArea). Our revised <body> area looks like this:
 

 
<body>
<input   type="button" value="Operating System" name="run_button" 
onClick="GetOSVersion">
<p>
<span id = "DataArea"></span>
</body>
 

We still have our button, but now we’ve added two more items to the body. First, we added a <p> tag; this is just a paragraph tag, something we added to put a little bit of space between our button and the data to be displayed. Second we added a <span> tag, setting the id to DataArea; that’s what we do here:
 

 
<span id = "DataArea"></span>
 

Notice that our <span> is empty; there’s nothing between the starting and closing tags. If we wanted to, we could put something there to start with. For example, this revised tag has some instructions to the user:

<span id = "DataArea">Click the button to return information about 
the operating system.</span>
 

When we click the button this instructional message will disappear and be replaced by the information returned from the GetOSVersion subroutine.

So how exactly do we accomplish all this? If you recall, in the first incarnation of our HTA we retrieved the operating system version and then displayed that information using the Msgbox function. The code for doing that looked like this:

 
Msgbox objOperatingSystem.Caption & " " & _
    objOperatingSystem.Version
 

Now take a look at our revised code:

 
DataArea.InnerHTML = objOperatingSystem.Caption & " " & _
    objOperatingSystem.Version
 

What we’ve done here is replace Msgbox with this:

 
DataArea.InnerHTML =
 

InnerHTML is a property of the <span> tag; it simply refers to everything contained inside the <span> and </span> tags, including text, HTML formatting, and other HTML tags. All we do here is set the InnerHTML property of the span named DataArea to the operating system version. What if, for some unknown reason, we wanted to set the value of InnerHTML to “No information available.”? Then we’d use code like this:

 
DataArea.InnerHTML = "No information available."
 

Each time we change the value of the InnerHTML property the old value is deleted and the new value takes its place.

Learn By Doing. If you’ve been doing the Learn By Doing exercises then you should have an HTA that includes a button named Service Pack; when that button is clicked it runs a subroutine named GetServicePack. At the moment, GetServicePack displays the returned information in a message box. See if you can modify the body of the HTA and the GetServicePack subroutine to write the returned information to the HTA itself (like, say, maybe in a <span>….). If you have problems figuring out how to do this, click here.

 

Did Someone Say Formatting?

Ah, yes. Those of you used to writing scripts that run in a command window might have forgotten that fonts can actually come in different sizes, styles, and colors. We won’t spend a lot of time talking about formatting today; suffice to say that any formatting that can be applied using HTML tags can be included within the InnerHTML property. For example, suppose you were creating a regular Web page and wanted some of the text displayed in red Arial. How would you do that? Well, you’d likely do something like this:

 
<font color='red' face='Arial'>No information available.</font>
 


As you can see, we enclosed the text itself inside the <font> and </font> tags. As part of the <font> tag, we assigned values to the color and face attributes. That’s it; it’s that easy.

So how would we specify this same formatting when assigning a value to the InnerHTML property? Why we’d just use the exact same syntax:

 
DataArea.InnerHTML = "<font color='red' face='Arial'>No information 
available.</font>"
 


Still not satisfied? Would you like this text to be boldface as well? Then just add the <b> and </b> tags:

 
DataArea.InnerHTML = "<b><font color='red' face='Arial'>No 
information available.</font></b>"
 


If you want to change the size or make the text blink (not recommended) or do any of the other things you can do with text then just add the appropriate HTML tags. For more information about the formats that can be applied to HTML elements take a look at the
HTML and DHTML Reference on MSDN.

Displaying Multi-Line Data

As we Tech Guys are wont to do, we seem to have wandered off-track a little: didn’t this whole <span> discussion come up because we wanted a way to display the names of all the running processes in our HTA? As a matter of fact, it did. So maybe we should take a look at that.
This isn’t particularly hard, but it is a little bit tricky. Why? Well, suppose we use a subroutine similar to this:

 
Sub GetProcesses
 
    strComputer = "."
 
    Set objWMIService = GetObject("winmgmts:\\" & strComputer & 
"\root\cimv2")
    Set colProcesses = objWMIService.ExecQuery("Select * from Win32
_Process")
 
    For Each objProcess in colProcesses
        DataArea.InnerHTML = objProcess.Name
    Next
 
End Sub
 


OK, that looks pretty good, doesn’t it? Yes, it does; unfortunately, it doesn’t work. If you run this subroutine you’ll have only one process displayed in your HTA. What happened to the other 48 processes?

What happened is that we goofed when we set up the For Each loop that cycles through the collection of processes. Take a close look at what happens inside that loop: 

 
For Each objProcess in colProcesses
    DataArea.InnerHTML = objProcess.Name
Next
 

Each time we encounter a new process we set the InnerHTML to the name of that process. Remember what we said about InnerHTML: each time we assign InnerHTML a new value the old value - that is, whatever used to be between the <span> and </span> tags - disappears. That’s exactly what’s happening here. We write the name of the first process to InnerHTML, then loop around, get the name of the second process, and write that value to InnerHTML. That’s fine, except that writing a new value erases the previous value. This keeps going until we write the name of the last process in the collection, which - because we don’t overwrite it - ends up being the only item displayed.

No, not good at all. But that’s OK; this is easy enough to fix. The trick here is not to write to the InnerHTML property each time we get the name of a process. Instead what we want to do is save up the names of all those processes and - as soon as we have the entire collection - write the whole kit-and-kaboodle to the InnerHTML property. Let’s show you a revised subroutine, then explain what we did different. (Notice, if you’re cutting and pasting as we go, the name of this new subroutine. You’ll need to change your onClick process to match. It would also make sense to change the name of the button to something like “Processes.”)

 
Sub GetProcesses
 
    strComputer = "."
 
    Set objWMIService = GetObject("winmgmts:\\" & strComputer & 
"\root\cimv2")
    Set colProcesses = objWMIService.ExecQuery("Select * from Win32
_Process")
 
    For Each objProcess in colProcesses
        strHTML = strHTML & objProcess.Name & "<br>"
    Next
 
    DataArea.InnerHTML = strHTML
 
End Sub
 

 

There are two major differences here. To begin with, we’ve radically revised our For Each loop:

 
For Each objProcess in colProcesses
    strHTML = strHTML & objProcess.Name & "<br>"
Next
 

Notice that we no longer set the value of the InnerHTML property. Instead each time we loop through the collection of processes we assign a variable named strHTML the following:

·         The existing value of strHTML

·         The name of the process

·         The HTML tag <br>

Why? Well, suppose the first time we run through the loop we encounter a process named winword.exe; consequently strHTML will equal this:

 
winword.exe<br>
 


How did we get that? This is just the value of strHTML (which, the first time through the loop, is equal to nothing) plus the name of the process (winword.exe) plus the <br> tag. We now loop through a second time and encounter a process named outlook.exe. Our variable strHTML now equals this:

  
winword.exe<br>outlook.exe<br>
 


Again, we simply took the existing value of strHTML - winword.exe<br> - and tacked on the name of the next process - outlook.exe - and another <br> tag. We keep repeating this process until we have looped through the entire collection.

Only then do we actually assign a value to the InnerHTML property. And this time around we assign InnerHTML the value of the variable strHTML, which just happens to contain a list of all the process names. Here’s the code that takes care of that:

 
DataArea.InnerHTML = strHTML
 

When we run the HTA and click the Processes button we get back something like this:

hta_10


That’s more like it!

Why All the <br> Tags?

Good question. Remember that we’re dealing with HTML here and in HTML the <br> tag represents a carriage return-linefeed: it’s like being in * Notepad and pressing the ENTER key. If we want an item (such as a process name) to start on the next line we need to include a <br> tag; it’s as simple as that. Suppose we left out the <br> tag, and had a subroutine similar to this:

 
Sub GetProcesses
 
    strComputer = "."
 
    Set objWMIService = GetObject("winmgmts:\\" & strComputer &_
 "\root\cimv2")
    Set colProcesses = objWMIService.ExecQuery("Select * from 
Win32_Process")
 
    For Each objProcess in colProcesses
        strHTML = strHTML & objProcess.Name
    Next
 
    DataArea.InnerHTML = strHTML
 
End Sub
 


Here’s what we’d get when we ran the subroutine:

hta_11

 

Instead of having a nice list of processes - one process per line - we have a huge single line of processes, all glommed together (there isn’t even a space to separate the individual process names). That’s because we need to manually enter line breaks, which is why we need all those <br> tags.

Yeah, that was a pretty dramatic demonstration, wasn’t it?


Learn By Doing
. Thus far we’ve simply echoed one property value - Name - for each process running on a computer. See if you can modify the subroutine so that it echoes an additional property value - ProcessID - on the same line. Your finished HTA should look something like this:

hta_12


Displaying Data in a Table

Our preceding HTA (from the last Learn By Doing exercise) displays the value of two different properties. And, to be honest, our output looks fine; with the two dashes it’s not too hard to figure out where one property value ends and another begins. Suppose, however, that we were displaying 4 or 5 values on a single line? Output like this is a bit harder to decipher:

hta_13


How can we make this output easier to deal with? Well, one way is to display the information as a table. We don’t have time to talk about tables this month; we’ll have to save that for another time. Just to whet your appetite a little, however, here’s a variation on our last Learn By Doing exercise. This subroutine displays both the process name and the process ID; the difference is that it displays this information in a two-column table:

 
Sub GetProcesses
 
    strComputer = "."
    Set objWMIService = GetObject("winmgmts:\\" & strComputer & _
        "\root\cimv2")
    Set colProcesses = objWMIService.ExecQuery("Select * From 
Win32_Process")
    strHTML = "<table border='1' style='border-collapse: collapse' 
"  & _
        "bordercolor='#111111' width='100%' id='Table1' >"
 
    For Each objProcess in colProcesses
        strHTML = strHTML & "<tr>"
        strHTML = strHTML & "<td width='50%'>" & objProcess.Name &_
 "</td>"
        strHTML = strHTML & "<td width='50%'>" & _
objProcess.ProcessID & _
            "</td>"
    Next
 
    strHTML = strHTML & "</table>"
    DataArea.InnerHTML = strHTML
 
End Sub
 




And here’s what the actual HTA looks like after the subroutine runs:

hta_14


Throughout this month’s tutorial we’ll periodically stop and give you a chance to test your new-found knowledge by asking you to write an HTA incorporating the current topic (for example, adding a drop-down list box to an HTA). Just to prove that we’re not totally heartless, we’ve provided this basic template that can be used in all of the exercises:

 
<html>
<head>
<title>HTA Test</title>
<HTA:APPLICATION 
     ID="objTest" 
     APPLICATIONNAME="HTA Test"
     SCROLL="yes"
     SINGLEINSTANCE="yes"
> 
</head>
 
<SCRIPT LANGUAGE="VBScript">
 
' PUT YOUR SUBROUTINES HERE
 
</SCRIPT>
 
<body>
 
' PUT THE HTML TAGS HERE
 
</body>
 

To use the template, copy the preceding code and paste it into * Notepad (or some other text editor). Replace the line ‘ PLACE YOUR SUBROUTINES HERE with the script code and the line ‘ PUT THE HTML TAGS HERE with your HTML code. Save the whole thing with a .hta file extension, and you’ll have yourself a (keep your fingers crossed) fully-functional HTA.

Adding a Drop-down List Box

There’s definitely a coolness factor to HTAs: after all, an HTA looks way cooler than a script that runs in a command window. On the other hand, looks aren’t everything (fortunately for the Tech Guys). In fact, there’s no point in creating an HTA unless the HTA does something a regular script can’t do.

So what can an HTA do that a plain-old .vbs file can’t? Well, suppose you have a number of file servers and you periodically
need to run a script to retrieve information from one of those computers. How can you target a single script to just one of your many file servers? Well, one tried-and-true way is to use command-line arguments; thus:

 
cscript myscript.vbs /server:server-fs-01
 

What’s wrong with using command-line arguments? Nothing, absolutely nothing.

Well, OK, you do have to type in the computer name each time. And you do have to type that name in correctly each time. And you do have to memorize all the names of all your file servers. None of that is particularly inviting, but what choice do you have?

Well, how about this for a choice: you take an HTA, add a drop-down list box pre-populated with the names of all your file servers, and then simply select a name from the list any time you want to run a script. No typing (or typing errors) and no memorization of server names required.

In other words, a drop-down list box (like the one shown below) is not only aesthetically-pleasing, but can be a time- and frustration-saver as well.

hta_15


Yes, we do make a pretty convincing case, don’t we? Of course, we did leave out one minor point: how exactly do you add a drop-down list box to an HTA? Relax; we wouldn’t build your hopes up like that and then let you down. As it turns out, the code for creating a drop-down list box (just like the code for creating all the other controls we’ll show you in this article) is pretty simple and straightforward:

 
 <select 
	size="1" name="OptionChooser" onChange="TestSub">b">
    <option value="1">Option 1</option>
    <option value="2">Option 2</option>
    <option value="3">Option 3</option>
</select>
 

 
See, that’s not so scary, is it? This standard HTML code starts off - as all drop-down lists and list boxes do - with a <select> tag. We simply type in a <select> tag along with the following parameters:

·         size. This is the number of options that appear onscreen at any one time. Setting the size to 1 gives us a drop-down list. What if we set the size to something other than 1? Well, we don’t want to spoil the surprise, but we’ll talk about that when we talk about list boxes. For now, just remember this: if you want a drop-down list, set the size to 1.

·         name. This is the name given to the control, and the name we’ll use in our scripts to refer to that control. For example, to echo the value of our drop-down list (that is, to determine which option was selected) we use this single line of code:

 
Msgbox OptionChooser.Value
 

·         onChange. This is the event handler for the control. What we’re saying here is pretty simple: any time the value of this control changes (that is, any time someone selects a different option) run this subroutine (in this example, the subroutine named TestSub).

We should point out that including an event handler (onChange) as part of the control is purely optional; we don’t have to run a script any time someone makes a selection in the drop-down list. Serverernatively, we could have the user make a selection and then click a button in order to run a script; it’s up to you to decide which approach you like the best. We should * Note, however, that there’s actually a problem with the control as currently configured, something we’ll discuss in more detail - and resolve - at the end of this section.

After the <select> tag, we stuff in three more lines of code, then add a closing </select> tag to indicate that we’re done configuring this particular control. There you go: your very first drop-down list box.

Oh, good point: what about that stuff between <select> and </select>?

 
<option value="1">Option 1</option>
<option value="2">Option 2</option>
<option value="3">Option 3</option>
 

As you probably figured out (the tag name <option> is a dead giveaway, isn’t it?) these are the list options, the actual items that appear when you click the drop-down list. Each individual item in the list consists of the following pieces:

·         The <option> tag, with a unique value parameter. The value parameter can be anything you want, though the values should be unique. And while the values can exactly match the displayed text, they don’t have to; in our preceding example, the first option has a value of 1 but the displayed text is Option 1. When we use a subroutine to determine which option was selected, we will typically work with the value of the option.

·         The displayed text. Anything that lies between the <option> tag and the </option> tag will be displayed as-is in the   
             drop-down list. In the example our first option shows up as Option 1 in the drop-down list. What if we wanted it to


show up as Ping remote computer? Then we’d configure the option like this:

 
<option value="1">Ping remote computer</option>
 

* Note that we don’t need to change the value; as we said earlier, values can be anything we want them to be.

·         The closing </option> tag. Simply so we know where one option leaves off and the next one begins.

You might have noticed that we don’t give the individual options their own names. Why? Because we have no reason to name individual options. Instead, when you select an option the value of the selected option gets passed to the <select> object. This allows us to determine which option was selected by examining the value of the <select> object. (In case you’re wondering, that’s why option values need to be unique.) For example, here’s a simple little subroutine that reports back the value of the selected option:

 
Sub TestSub
    Msgbox "You selected Option " & OptionChooser.Value & "."
End Sub
 

See? All we do is report back the value of the drop-down list itself (OptionChooser), which will just happen to be exactly the same as the value of the selected option. (Keep in mind that the value is going to be 1, 2, or 3, because those are the values we assigned the individual options.)

So What’s Wrong with the Control as Configured?

We showed you a simplistic version of the drop-down list because we wanted you to see how easy it is to implement HTML controls in an HTA; consequently, we wanted to keep the code as short and concise as we could. However, there is a problem with the control and the onChange event. When you load the HTA, Option 1 will automatically be selected. That’s fine, but suppose you want to run the script against Option 1; how do you do that? Believe it or not, it’s tougher than you think. After all, you can’t select the option; it already is selected. Because of that, clicking the option won’t trigger the onChange event; onChange won’t get triggered because nothing has changed. In fact, as configured, the only way to select Option 1 is to first select, say, Option 2 (which causes the script to run against that option) and then select Option 1.

Eep.

But don’t worry, there’s an easy way to fix this. All we need to do is add a blank option at the top, using code similar to this:

 
<select size="1" name="OptionChooser" onChange="TestSub">
    <option value="0"></option>
     <option value="1">Option 1</option>
    <option value="2">Option 2</option>
    <option value="3">Option 3</option>
</select>
 

Notice that our first option - with the value 0 - has no displayed text; it will appear blank in the drop-down list. We then need to modify our subroutine to ensure that the script runs only if the value of the selected option does not equal 0. In other words, the script will not run if you select the blank option:

 
Sub TestSub
    If OptionChooser.Value <> 0 Then
        Msgbox "You selected Option " & OptionChooser.Value & "."
    End If
End Sub
 

Make sense? If not, try this complete HTA and you’ll see exactly what we mean:

 
<html>
<head>
<title>HTA Test</title>
<HTA:APPLICATION 
     ID="objTest" 
     APPLICATIONNAME="HTA Test"
     SCROLL="no"
     SINGLEINSTANCE="yes"
> 
</head>
 
<SCRIPT LANGUAGE="VBScript">
 
    Sub TestSub
        If OptionChooser.Value <> 0 Then
            Msgbox "You selected Option " & OptionChooser.Value &_
 "."
        End If
    End Sub
 
</SCRIPT>
 
<body>
 
<select size="1" name="OptionChooser" onChange="TestSub">
    <option value="0"></option>
    <option value="1">Option 1</option>
    <option value="2">Option 2</option>
    <option value="3">Option 3</option>
</select>
 
</body>
 

Click Option 1, 2, or 3 and you’ll see a message box reporting the option you selected. Click the blank option and nothing will happen. Problem solved.

Learn By Doing

OK, let’s see what you’ve learned so far. For our first try-it-yourself exercise, see if you can create an HTA that includes a drop-down list box with the following computer names as options:

·         server-dc-01

·         server-dc-02

·         server-dc-03

When you select one of the options, a subroutine should report back the name of the selected computer. (Hint: To do that, you might want to make the value of each option identical to the displayed text.) If you have problems getting this to work, click here to see the answer.

* Note. Some of you might be wondering, “Is it OK to cheat? Is it OK to copy code out of the article, paste it into my exercise, make a minor modification or two, and then pass that off as a finished assignment?” You bet it is; in fact, that’s the kind of thing we encourage you to do. After all, we just want you to be able to create HTAs; if you find that “cheating” is the easiest/fastest way to create an HTA, then cheat away.

 

Adding a List Box

By definition a drop-down list box shows only one item at a time; if you want to see additional items you need to click the control and drop down a list of additional items. There’s nothing wrong with that; however, there might be times when you’d find it easier/more effective to see multiple options at the same time. In other words, there might be times when you want to use a list box rather than a drop-down list:

hta_16


Hey, why not; after all, variety is the spice of life. So let’s talk about adding a list box to an HTA.

One of the best things about list boxes is this: after you know how to create and use a drop-down list you’ll know how to create and use a list box as well. For example, here’s the code that creates a list box (shown above) with three options:

 
<select size="3" name="OptionChooser" onChange="TestSub">
    <option value="1">Option 1</option>
    <option value="2">Option 2</option>
    <option value="3">Option 3</option>
</select>
 

What’s the difference between this code and the code that created the drop-down list? Just one thing: in this case we’ve set the value of the size parameter to 3. That means we want to show three options onscreen at the same time. If we set the size to 12 we’d show 12 options onscreen at the same time. And if we set the size to 1 we’d have a drop-down list. It’s that simple.

Incidentally, you don’t have to make a list box the same size as the number of options you have. What if you have 100 options but only have room onscreen to show 10 at a time? That’s fine: just set the size to 10 and a scroll bar will automatically be added to the list box, enabling you to scroll up and down and access all 100 options. Play around with this a bit and see for yourself.



Learn By Doing

This is basically the same exercise as the first; this time, however, we want you to use a list box instead of a drop-down list. See if you can create an HTA that includes a list box (one that shows three items at a time) with the following computer names as options:

·         server-dc-01

·         server-dc-02

·         server-dc-03

·         server-dc-04

·         server-dc-05

·         server-dc-06

When you select one of the options, a subroutine should report back the name of the selected computer. If you have problems getting this to work, click here to see the answer. For extra credit, remove the onChange event handler and see if you can add a button that will report back the name of the selected computer. If you have problems with that, don’t sweat it; we’ll review the code for adding a button later on.

Handy hint. After adding the list box be sure and include a <BR> tag or a <P> tag; that will ensure that your controls don’t line up horizontally across the screen.

 

Adding a Multi-Select List Box

We have one more list box variation to show you. In HTML you can create something known as a multi-select list box. With a multi-select list box you can hold down the Ctrl key and select as many options as you want. For example, do you need to select options 2, 4, and 5, all at the same time? Then go ahead and do it:

hta_17


We understand your concerns: no doubt creating a multi-select list box takes a lot of very sophisticated, highly-technical skill, the kind of skill only a Scripting Guy could have. Just how complicated is creating a multi-select list box? This complicated:

 
<select size="3" name="MultiListbox" multiple>
    <option value="1">Option 1</option>
    <option value="2">Option 2</option>
    <option value="3">Option 3</option>
</select>
 

No, we didn’t paste the wrong code in by mistake. The truth is that creating a multi-select list box is pretty much like creating a regular old list box. In fact, there are only two differences:

·         We added the multiple attribute to the <select> tag. That’s what turns a plain-old list box into a way-cool multi-select list box.

·         We removed the onChange event from the <select> tag. Why? Well, we don’t want to run a script each time the list box changes in some way; if that happened we’d select the first option and then the script would run, without waiting for us to select additional options. Instead we want the user to be able to select all the desired options and then click a separate button to kick off a script. Thus we need to remove the onChange event handler and then add a button that will run the TestSub subroutine.

In fact, the only tricky part about adding a multi-select list box crops up when you need to determine which options - if any - were selected. You can’t just echo back the Value when dealing with a multi-select list box; the singular notion “Value” is meaningless when you can have multiple items with multiple values. Instead, you’ll have to loop through all the options and determine which ones have a Selected property equal to True. That’s how you can identify which items have been selected and which ones haven’t.

No, it’s not too hard. In fact, all it takes are a few lines of code:

 
Sub TestSub
    For Each objItem in MultiListbox.Options
        If objItem.Selected Then
            strSelected = strSelected & objItem.Value & vbCrLf
        End If
    Next
    Msgbox "You selected the following items: " & vbCrLf &_
 strSelected
End Sub
 



See? All we do is create a For Each loop to cycle through all the options (items) in the list box; that’s what this line of code does:

 
For Each objItem in MultiListbox.Options
 

For each option (item) we check the value of the Selected property. If Selected is True that means the item was selected; we then store the value of that particular option in a variable named strSelected. If Selected is False we don’t do anything except move on to the next item in the collection. After looping through the entire set of options we then echo back a message similar to this, detailing the options that were selected:

hta_18


That’s all there is to it.

Incidentally, if you never did figure out how to add a button to your HTA, here’s a hint:

 
<input id=runbutton  type="button" value="Run" name="run_button"  
onClick="TestSub">
 


Learn By Doing

Similar to the previous two exercises, see if you can create an HTA that includes a multi-select list with the following computer names as options:

·         server-dc-01

·         server-dc-02

·         server-dc-03

·         server-dc-04

·         server-dc-05

·         server-dc-06

In addition, your HTA should include a button that, when clicked, calls a subroutine that reports back all the options that were selected. (Remember, with a multi-select list box you can hold down the Ctrl key and select more than one option at a time.) If you have problems getting this to work, click here to see the answer.

 

Adding a Check Box

Picture an HTA that lists a number of different scripts you can run against a computer; maybe there’s a script that performs a hardware inventory, one that performs a software inventory, another that retrieves performance statistics. (Yes, it’s exactly the way medieval mystics pictured Paradise.) When you load that HTA, you’d like to be able to pick and choose which scripts to run and which scripts not to run. Maybe this time out you want to run the two inventory scripts but not the performance script; the next time out maybe you want to do the hardware inventory and get the performance statistics.

In other words, you want options that can be toggled on and off independently (that is, choosing the hardware script doesn’t automatically cause you to run the software script). If you’re thinking to yourself, “Hmmm, this sounds like a job for a check box,” you’re absolutely right:

hta_19


The check box is just another variation of the <input> control (a control we learned about last month), this one with a type of, well, checkbox:

 
<input type="checkbox" name="Checkbox1"> Checkbox 1
 

Basically all you have to do is add an <input> tag along with the type and name parameters. (* Note: No closing tag - that is, no </input> tag - is required.) After adding the tag simply type the label that appears next to the tag. In our preceding example, we gave the check box the label Checkbox 1. (Yes, they do pay us to think up stuff like that. Why do you ask?) If we wanted a check box with the label Run disk cleanup script we’d use this code:

 
<input type="checkbox" name="Checkbox1"> Run disk cleanup script
 
<input type="checkbox" name="Checkbox1" value="Checkbox1" 
checked=True> Checkbox 1

 

To determine whether or not a check box has been checked all we do is look at the value of the Checked property. If True then the box is checked; if False, then the box is not checked. Here’s some sample code that does that checking for us:

 
Sub TestSub
    If Checkbox1.Checked Then
        Msgbox "You checked the check box."
    Else
        Msgbox "You did not check the check box."
    End If
End Sub
 


What if we have more than one check box in the HTA? In that case, you just need to write separate If-Then blocks that examine the Checked property of each of those check boxes. In other words:

Sub TestSub
    If Checkbox1.Checked Then
        Msgbox "You checked check box 1."
    Else
        Msgbox "You did not check check box 1."
    End If
    If Checkbox2.Checked Then
        Msgbox "You checked check box 2."
    Else
        Msgbox "You did not check check box 2."
    End If
End Sub  
 



* Note that we do two things in this subroutine: first we look at the value of the Checked property for Checkbox1, then we do the same thing for Checkbox2.


Learn By Doing

Create an HTA that includes two check boxes, one labeled server-dc-01 and one labeled server-dc-02. The HTA should also include a button that, when clicked, tells you whether either (or both) of the two check boxes has been checked. If you have problems getting this to work, click here to see the answer.

 

Adding Radio Buttons

Radio buttons are designed for items that are mutually-exclusive: that is, you can be one of those things, but you can’t be more than one of those things. For example, you can choose to save a file or you can choose not to save a file, but you can’t choose to simultaneously save and not save a file. (That sounds like one of those clever human tricks Captain Kirk would use on the old Star Trek show to send a computer into an endless loop and once again defeat cold-blooded logic. We’d like to see Captain Picard do that.)

In other words, radio buttons are different from check boxes. Suppose you had 10 check boxes on screen. By definition you could select any 2 or any 5 or even all 10 of those check boxes. With radio buttons (shown below) things are very different: you can select one - and only one - radio button within a group:

hta_20 


Yes, hardly the control for the Me Generation; after all, nowadays we want it all. But with a radio button, you only get one.

We should mention from the outset that the radio button is not the most intuitive HTML control you’ll find yourself using. Up to this point all the controls we’ve created have had unique names. That makes sense; how else would you distinguish one control from another? With radio buttons, however, things are different. Say we want to create a group of three radio buttons, like the group we just showed you. In that case, we need to create three separate radio buttons, each with the exact same name.

No, we’re totally serious: all the radio buttons in a group must have the same name (serverhough they should have different values). That’s how our script knows that these buttons belong together. (In other words, that’s how the script knows that these buttons are mutually-exclusive.) If that doesn’t make sense, don’t worry; we’ll show you exactly how it works.

Here’s some HTML code that creates radio buttons labeled Option 1, Option 2, and Option 3:

<input type="radio" name="RadioOption" value="1">Option 1<BR>
<input type="radio" name="RadioOption" value="2">Option 2<BR>
<input type="radio" name="RadioOption" value="3">Option 3<P>
 

As you can see, all three of these buttons have the same name: RadioOption. That leads to the obvious question: if all the buttons have the same name, how can you tell them apart? That is, how can you tell if a user selected Option 1 rather than Option 2 or Option 3?

Good question. When it comes to radio buttons, all the controls with the same name are put into an array that has the same name as the control (in our preceding example, that means an array named RadioOption). To determine which button was selected all we have to do is set up a For Each loop to loop through that array, taking a peek at each button and seeing whether or not the Checked property is True. If Checked is True, then that button was selected. Your code for looping through an array of radio buttons might look something like this:

 
Sub TestSub
    For Each objButton in RadioOption
        If objButton.Checked Then
            Msgbox "You selected Option " & objButton.Value & "."
        End If
    Next
End Sub
 

As you can see, all we’re doing is looking to see whether or not the Checked property is True; if it is, we then echo back the button Value (this, by the way, is why button Values need to be unique). If the Checked property isn’t True, we don’t do anything at all. Like we said, not the most intuitive thing in the world, but it works.

Incidentally, it’s possible to have more than one group of radio buttons within the same HTA; just make sure that each group is given a different name. If you have a set of radio buttons, all with the name RadioOption, then you’ll want to give your next set of radio buttons a name like SecondRadioOption. As you’ve probably figured out by now, all the names you give to controls are arbitrary; name your controls whatever you want. (Just make sure you avoid using blank spaces anywhere in the name.)


Learn By Doing

For this exercise, let’s see if we can create an HTA that includes a group of radio buttons; the individual radio buttons should have the following computer names as labels:

·         server-dc-01

·         server-dc-02

·         server-dc-03

The HTA should also have a button that, when clicked, reports back the name of the selected computer. If you have problems getting this to work, click here to see the answer.


Adding a Text Box

Drop-down lists, radio buttons and other fancy user interface controls can be a great timesaver for your users: it’s much faster (and much less error-prone) to have users select from a predetermined set of computers than it is to have them type in the desired computer name. However, you can’t always provide your users with predetermined options. For example, suppose you have an HTA for creating user accounts. There’s no way to provide drop-down lists pre-populated with all the possible first names and all the possible last names for a new user; it just won’t work. Instead, you have to provide a mechanism that allows people to enter any information. And the best mechanism for that is the humble - yet highly useful - text box:

hta_21


U
seful, and very easy to implement: to add a text box to your HTA just use an <input> tag, specifying the type (text), a name, and, optionally, the size (that is, the number of characters wide):

 

<input type="text" name="BasicTextbox" size="30">

If you don’t include a size, by default the text box displays 20 characters.

Handy hint. The size of a text box is just the width of the text box onscreen; in no way does the size determine the number of characters that can be typed into a text box. If you do want to limit the number of characters a user can type into a text box then add the maxLength parameter. For example, this code displays a text box 30 characters wide, but only allows you to type a maximum of 25 characters: 

 
<input type="text" name="BasicTextbox" size="30" maxLength="25">
 


Little-known historical fact
. The Tech Guys once participated in a “post-mortem” for a project that took a couple years to complete and was riddled with problems all the way through. We were allowed to air our complaints using an online form…a form that accepted a maximum of 255 characters in the Complaints box. In case you’re wondering, this * Note consists of 392 characters by itself.

 

So how can we retrieve the information that’s been typed into a text box? That’s easy: we just have to retrieve the Value property. For example, this simple little subroutine echoes back whatever’s been typed into a text box named BasicTextbox:

 

 
Sub TestSub
        Msgbox BasicTextbox.Value
End Sub
 

By the way, it’s also very easy to programmatically “type” something into a text box. All you have to do is set the Value of the text box. For example, this subroutine “types” Fabrikam, Inc. into a text box named BasicTextbox:

 

 
Sub TestSub
    BasicTextbox.Value = "Fabrikam, Inc."
End Sub
 

Would you ever want to do something like this? Sure. Suppose you have a tool for creating a new user account. The person creating the account selects the department from a drop-down list. If, say, all members of the Accounting department work in the same building in the same city, then you could have a subroutine that automatically fills in the building and city. Yet another reason why HTAs are so handy.


Learn By Doing

This is an easy one: create an HTA that includes a text box and a button; when the button is clicked, it should report back whatever was typed into the text box. If you have problems getting this to work, click here to see the answer.



Adding a Multi-Line Text Box

The standard text box is fine if you’re entering nothing more than a first name or last name; because the text box is limited to a single line, however, it’s not as useful for entering anything more substantial. If you need more room to enter (or to display) text, then you can use the <textarea> control, and get something that looks like this:

hta_22


Now that’s more like it. And don’t worry; configuring a multi-line text box is very easy:

 
<textarea name="ScriptArea" rows=5 cols=70></textarea>
 

As you can see, all we need to do is toss in a <textarea> tag (and the accompanying </textarea> tag) and set the following parameters:

·         name. The name of the control.

·         rows. The number of lines that appear onscreen. A scrollbar will automatically be added to the control to enable you to type additional lines.

·         cols. The width of the control, in characters. If you set cols to 70 then you should be able to type 70 characters, using Courier 12-point, on a single line.

You retrieve the value of a multi-line text box the same way you retrieve the value of a regular text box:

 
Sub TestSub
    Msgbox ScriptArea.Value
End Sub
 


That’s true. But you don’t have to tell anyone how easy that is. Let them think you’re doing something only a programming genius could do!


Learn By Doing

This is a variation on the previous exercise. Instead of creating an HTA that includes a text box and a button, create an HTA that includes a multi-line text box and a button. The multi-line text box (textarea) should be sized for 40 columns and 5 rows; the button, when clicked, should display whatever was typed into the text box. If you have problems getting this to work, click here to see the answer.

Adding a Password Box

One final control we want to introduce is the password box. The password box is just like the text box, but with one important exception: everything you type into a password box is “masked” so that the characters are not visible onscreen. In other words:

hta_23


The code for adding a password box is almost identical to the code for adding a text box. To add a password box you use the <input> tag and you specify a name and size; the only difference is that you set the type to “password” rather than “text”:

 
<input type="password" name="PasswordArea" size="30">
 


And, yes, you’re absolutely right: retrieving the information typed into a password box is as simple as getting back the value of that control:

 
Sub TestSub
    Msgbox PasswordArea.Value
End Sub
 


  About

  
I'm a Computer
  
Systems Engineer

  
Living and loving life
........................................


 
Author

 ..