How Can I Temporarily Pause a Script in an HTA?


Hey, Scripting Guy! Question

Hey, Scripting Guy! How can I temporarily pause a script in an HTA?

— TJ

SpacerHey, Scripting Guy! AnswerScript Center

Hey, TJ. You know, throughout history people have spent an enormous amount of time and energy searching for the meaning of life. The Scripting Guys have never taken part in this quest. Why not? Well, laziness aside, we know that it doesn’t matter: even if you did find the meaning of life, no one would care. No one wants to know why we exist; instead, they – like you – just want to know how the heck they can pause a script embedded in an HTML Application (HTA). That’s the cause the Scripting Guys have dedicated their lives to.

Now, if you’re not familiar with HTAs you’re first thought will likely be, “Just use Wscript.Sleep.” (Incidentally, if you’re not familiar with HTAs, you might want to wander over to the HTA Developers Center.) That’s a good thought, but it won’t work. Why not? That’s because the Wscript object is a somewhat-unique object; for one thing, you can’t actually create an instance of this object. Instead, the Wscript object is automatically provided for you any time you’re running under Windows Script Host. And that’s the problem right there: when you’re running code within an HTA you are not running under Windows Script Host. Instead, you’re running under the script host provided by Internet Explorer. Because you’re not running under Windows Script Host you aren’t automatically given access to the Wscript object, and because you can’t create the Wscript object on your own there’s no way to access Wscript.Sleep. You are – in highly-technical terms – hosed.

This wouldn‘t be that big of a deal if Internet Explorer provided a method comparable to Wscript.Sleep; unfortunately, it doesn’t. So is there some kind of crazy workaround we can use instead of a Sleep method? Did you even have to ask?

<script language = “VBScript”>

Dim dtmStartTime

Sub Test dtmStartTime = Now idTimer = window.setTimeout(“PausedSection”, 5000, “VBScript”) End Sub

Sub PausedSection Msgbox dtmStartTime & vbCrLf & Now window.clearTimeout(idTimer) End Sub


<body> <input id=runbutton type=”button” value=”Run Button” onClick=”Test”> </body>

What we have is a very simple HTA: it consists entirely of a single button that, when clicked, runs a subroutine named Test. Big deal, you say? Well, let’s take a look at the <SCRIPT> section of our HTA and decide how big a deal it really is.

The first thing we do within the <SCRIPT> section is declare a global variable named dtmStartTime:

Dim dtmStartTime

This actually has nothing to do with pausing the script; instead it’s just a variable we use to help us see that the script really did pause as expected. If that doesn’t make any sense to you at the moment, just be patient: it should all become clear very soon.

Next we have the Test subroutine, which gets called when we click the button:

Sub Test
    dtmStartTime = Now 
    idTimer = window.setTimeout(“PausedSection”, 5000, “VBScript”)
End Sub

Notice that we have just two lines of code in this subroutine. In the first line we simply assign the current date and time (using the Now function) to the variable dtmStartTime. That brings us to this line of code:

idTimer = window.setTimeout(“PausedSection”, 5000, “VBScript”)

Believe it or not, this is how we mimic the function of the Sleep method. What we’re doing here is using the setTimeout method to create a timer, which we give the ID idTimer. As you can see, we pass setTimeout three parameters:

PausedSection. This is the name of the subroutine we want to run when the timer expires.

5000. This is the amount of time (in milliseconds; 5000 milliseconds equals 5 seconds) we want the timer to wait before calling PausedSection. In other words, that’s our pause. If we want to pause the script for 30 seconds then we’d set this parameter to 30000.

VBScript. A required parameter that simply lets the script know that PausedSection is written in VBScript.

In other words, when we click the button the Test subroutine will run. When the Test subroutine runs, it creates a timer named idTimer. The sole function of idTimer is to wait 5 seconds and then call the subroutine PausedSection. Does that make sense? Good.

So what do we do inside the subroutine PausedSection? Well, obviously we could run any code we wanted; for simplicity’s sake we do only two things here. First, we display a message box showing the time we clicked the button and the time that the message box itself actually appeared on screen:

Msgbox dtmStartTime & vbCrLf & Now

Allowing for rounding errors, the difference between the time we clicked the button and the time the message box appeared should be 5 seconds. Is that important? You bet it is. Remember, displaying this message box is the first thing that happens inside the PausedSection subroutine. If it shows up 5 second after we click the button then that means we paused our script for 5 seconds. Which, as you might recall, was the whole idea in the first place.

The other thing we do inside the PausedSection subroutine is call the clearTimeout method and effectively get rid of our timer:


Why do we do that? That’s easy: timers are designed to run forever. If we don’t clear the timer then every 5 seconds idTimer will call the PausedSection subroutine, and every 5 seconds our little message box will pop up onscreen. We don’t really want to see that message box every 5 seconds, so we use clearTimeout to remove the timer.

Admittedly, this isn’t quite as easy as simply saying Wscript.Sleep 5000; that means you’ll probably have to think a little bit before you start enabling and disabling timers. In turn, that can be a bit of a challenge, but, hey, isn’t that what life’s all about?

And no, that wasn’t a rhetorical question. Like we said, we’ve been busy trying to pause HTAs; beyond that we have no idea whatsoever what life is all about.