How Can I Run a Subroutine in an HTA After a Set Amount of Time?
Hey, Scripting Guy! I have an HTA that asks users to either click a button to install some software or click Cancel. Sometimes, though, users don’t do either one; they just let the HTA sit there. Is there any way to show the HTA for a set amount of time and then, if nothing happens, have it go ahead and install the software?
Hey, TN. Well, today is February 14th, which just happens to be a very exciting and much-anticipated holiday. Yes, February 14th is that very special day, the day in which – what’s that? Valentine’s Day? Hold on a second … well, what do you know: today is Valentine’s Day. Wow. You know, we feel kind of sorry for the people who sell Valentine’s Day cards and candy; what bad luck that Valentine’s Day happens to fall on the same day as a very exciting and much-anticipated holiday.
What holiday are we talking about? You must be joking, right? After all, everyone knows that today, February 14th, is Scripting Games Eve. That’s right, today is the day when people, giddy with expectations, make their final plans for the 2008 Winter Scripting Games, which officially kick off on Friday, February 15th. Sometime after midnight tonight, the Scripting Guys will climb into the Scripting Sleigh and fly all around the world, slipping down chimneys and leaving Scripting Games events for all the good little boys and girls.
OK, so maybe that was a bit of an exaggeration. The truth is, the Scripting Guys won’t be slipping down any chimneys, not unless the Scripting Guy who writes this column stops eating doughnuts every morning. (Getting stuck in someone’s chimney would be way too embarrassing.) However, we do plan to post the Scripting Games events sometime after midnight Pacific Standard Time. (See this column and this Web page for information on converting Pacific Standard Time to your local time.) And these will be available to everyone, not just the good little boys and girls.
After all, if we limited this to good little boys and girls the neither Scripting Guy Dean Tsaltas nor Scripting Guy Peter Costantini would be able to take part.
Now that you mention it, yes, that is a change in plans: originally we intended to post all the Scripting Games events at 8:00 AM Redmond time on February 15th. After giving this a little thought, however, we decided to post things a bit sooner than that; we saw that as a way to help out those of you who don’t live in the Pacific Standard Time time zone. (Which we still think is the greatest time zone in the world. You go, Pacific Standard Time time zone!)
At any rate, a Happy Scripting Games Eve to everyone, regardless of which time zone you live in. We know that many of you are very excited about the Scripting Games, so excited that you can’t even sleep. If that sounds like you, well, here’s a little something that will help you pass the time between now and the moment the Scripting Games events become available. This little something happens to be code for an HTML Application (HTA). But not just any HTA: this one waits to see if a user is going to click a button and then, if the user doesn’t do anything, goes ahead and runs a subroutine on its own. Here’s the code:
<SCRIPT Language = "VBScript"> Dim idTimer Sub Window_Onload idTimer = window.setTimeout("InstallSoftware", 5000, "VBScript") End Sub Sub InstallSoftware window.clearTimeout(idTimer) Msgbox "Installing software ..." End Sub Sub CancelInstall window.clearTimeout(idTimer) Msgbox "Installation cancelled." End Sub </SCRIPT> <BODY> <input type="button" value="Install" onClick="InstallSoftware"> <input type="button" value="Cancel" onClick="CancelInstall"> </BODY>
As you can see, there’s not much to this HTA. For example, the HTA <BODY> consists of just two buttons. The first button, labeled Install, is configured to run a subroutine named InstallSoftware any time the button is clicked:
<input type="button" value="Install" onClick="InstallSoftware">
The second button, labeled Cancel, is configured to run a subroutine named CancelInstall any time that it gets clicked:
<input type="button" value="Cancel" onClick="CancelInstall"
And that’s it. We told you there wasn’t much to this.
Now let’s take a look at the <SCRIPT> section of our HTA. To begin with, you might notice that we have one line of code that isn’t contained within a subroutine:
What we’re doing here is declaring a global variable named idTimer. By default, variables used in an HTA are accessible only to the subroutine where those variables are declared or first used. For example, consider this subroutine:
Sub VariableTest Dim strTest End Sub
Because strTest was declared inside the subroutine VariableTest that’s the only place that variable can be used; you can’t retrieve the value of strTest from another subroutine. The only time you can access a variable from another subroutine is when that variable is a global variable. And how do you create a global variable? You got it: you declare it inside the <SCRIPT> section of the HTA. (But not inside a subroutine.) Just do what we did, and have the Dim statement sitting on a line all by itself.
After declaring our global variable we next encounter this subroutine:
Sub Window_Onload idTimer = window.setTimeout("InstallSoftware", 5000, "VBScript") End Sub
As most of you probably know, in an HTA any subroutine named Window_Onload will automatically run any time that HTA is loaded or refreshed. So what are we going to do each time the HTA is loaded or refreshed? Just one thing; we’re going to use the setTimeout method to create a timer named idTimer:
idTimer = window.setTimeout("InstallSoftware", 5000, "VBScript")
A timer is pretty much what the name implies: it’s a control that’s going to count down for a specified amount of time and then take some sort of action. To create a timer we simply call the setTimeout method, passing setTimeout three parameters:
InstallSoftware. This is the name of the subroutine we want to run after the allotted time has elapsed.
5000. This is the amount of milliseconds we want to count down. Because there are 1000 milliseconds in every second that means our 5000-millisecond timer will count down for 5 seconds before calling the subroutine InstallSoftware.
VBScript. This simply tells the HTA which scripting language the InstallSoftware subroutine is written in.
So what’s all this going to do? Well, when the HTA first loads up it’s going to create the timer idTimer and the clock is going to begin ticking. After 5 seconds have elapsed, and if the user hasn’t done anything else, the timer will then call the subroutine InstallSoftware.
Speaking of which, let’s take a look at the InstallSoftware subroutine:
Sub InstallSoftware window.clearTimeout(idTimer) Msgbox "Installing software ..." End Sub
Again, pretty simple stuff here. In the first line we use the clearTimeout method to cancel our timer idTimer. Is that important? As a matter of fact it is: if we don’t explicitly cancel the timer then that timer will continue to run; in this case, that means that every 5 seconds the HTA will call the InstallSoftware subroutine. That’s probably not what we want it to do.
In line 2 we display a message box that notes that the software is being installed. Obviously you don’t need a message box here. (And you probably shouldn’t display one anyway. After all, that would cause the subroutine to stop dead in its tracks, at least until someone dismissed the message box.) Instead, this would be the spot where you put your code for installing the software, or for doing whatever it is you want the HTA to do.
To recap, we start the HTA, the timer starts ticking and, after 5 seconds the InstallSoftware subroutine kicks in. All of that happens automatically, without any user intervention. So then what do we need those two buttons for?
To answer that question, let’s first note that we configured out timer for 5 seconds simply for testing purposes. In real life, 5 seconds might not be enough time for a user to decide whether or not they want to install the software. Instead, you might create a timer that runs for, say, 30 seconds:
idTimer = window.setTimeout("InstallSoftware", 30000, "VBScript")
Now, if you wanted to, you could simply make your user sit there for 30 seconds and wait for the InstallSoftware subroutine to start up. Alternatively, that user could click the Install button and “manually” kick off the installation process at any time. Click the Install button and – regardless of how much time has elapsed – the timer will be cleared and software installation will begin.
Note. It’s important to keep in mind that this timer is not pausing the entire HTA; that is, it’s not functioning like the Wscript.Sleep command. Instead, the timer is running in the background, leaving us free to do other things in the HTA. Like, say, click one of buttons.
OK, now what about the Cancel button? Well, TN wants to give users the opportunity to cancel software installation. To do that, all they have to do is click the Cancel button, which, in turn, calls the following subroutine:
Sub CancelInstall window.clearTimeout(idTimer) Msgbox "Installation cancelled." End Sub
Notice what we’re doing in this subroutine. To begin with, we once again use the clearTimeout method to get rid of our timer. As soon as that’s done we display a message box noting that the installation process has been cancelled. But, again, that’s code we’re using merely for demonstration purposes; put whatever code you want here. For example, you could include this line of code, which causes the HTA to close any time a user clicks the Cancel button:
Alternatively, you could leave the HTA onscreen. That way the user could still install the software simply by clicking the Install button. But that’s up to you.
That’s should do it, TN; hopefully you can take this sample code and make it fit your exact needs. In the meantime, we’d like to once again wish everyone a very Happy Scripting Games Eve; we hope to see you back here tomorrow for Opening Day. (February, 15th, in case if we haven’t mentioned that enough times yet.) We should also point out that we know that way more people read this column each day than participate in the Games. Hey, what’s up with that? Come on, give the Scripting Games a try: it’s fun; it’s educational; you can compete anonymously if you want; and, best of all, you have numerous chances to win some great prizes. Based on all that, why wouldn’t you want to give the Games a try?
We should also take a minute to wish all of you a Happy Valentine’s Day. Did you know that, in Japan, it’s obligatory for women to give all their male co-workers chocolates on Valentine’s Day? It’s true. Are you listening, Scripting Guy Jean Ross?
Editor’s Note: Scripting Guy Jean Ross has no problem with that. That just means that as of March 14 (“White Day” in Japan) she can expect to finally get that new watch she’s been hoping for ….