How Can I Display A Progress Bar (or Something Similar) While My Script Runs?

How Can I Display A Progress Bar (or Something Similar) While My Script Runs?

  • Comments 6
  • Likes
Hey, Scripting Guy! Question

Hey, Scripting Guy! How can I get my script to do something interesting while the code executes; you know, how can I display a progress bar or something?

-- HD

SpacerHey, Scripting Guy! AnswerScript Center

Hey, HD. To begin with, we don’t recommend that you try to use a true progress bar; that’s because it’s very difficult to calculate - let alone display - progress. We’re all familiar with those so-called progress bars - some, alas, included in Microsoft products - that tell you that the estimated time to complete an operation is 3 minutes, then 296 minutes, then 1 minute, then 14 minutes. We don’t want to mess around with something like that.

Instead, we suggest you try a simple little dialog box (or at least something that looks like a dialog box) that merely informs the user that something is going on and asks them to be patient. When the operation is complete, our sample dialog box displays a message to that effect, and then disappears. It’s not fancy, but it works.

Here’s the code:

On Error Resume Next

Set objExplorer = CreateObject _
    ("InternetExplorer.Application")

objExplorer.Navigate "about:blank"   
objExplorer.ToolBar = 0
objExplorer.StatusBar = 0
objExplorer.Width = 400
objExplorer.Height = 200 
objExplorer.Visible = 1             

objExplorer.Document.Title = "Logon script in progress"
objExplorer.Document.Body.InnerHTML = "Your logon script is being processed. " _
    & "This might take several minutes to complete."

Wscript.Sleep 10000

objExplorer.Document.Body.InnerHTML = "Your logon script is now complete."

Wscript.Sleep 5000
objExplorer.Quit

All we’re doing here is creating an instance of Internet Explorer, then using this line of code to open up a blank page in the browser window:

objExplorer.Navigate "about:blank"

We get rid of the toolbar and the status bar (by setting those values to 0), and then set the size of our window to 400 pixels and 200 pixels. We then set the Visible property to 1, which actually displays our little Internet Explorer window on the screen. And just for the heck of it we configure the Title property for the window using this line of code:

objExplorer.Document.Title = "Logon script in progress"

The net result? Something that looks like this:

Internet Explorer

That’s almost OK in and of itself, but we can probably do a little better: for one thing, we can display a custom message in our Internet Explorer document. To do that we set the InnerHTML property of the document body:

objExplorer.Document.Body.InnerHTML = "Your logon script is being processed. " _
    & "This might take several minutes to complete."

What’s cool about this is that we can use all our favorite HTML tags when assigning a value to the InnerHTML property. For example, suppose we want this message displayed in bold. In that case, we just need to include the <B> and </B> tags:

objExplorer.Document.Body.InnerHTML = "<B>Your logon script is being processed. " _
    & "This might take several minutes to complete.</B>"

After setting the InnerHTML property, we have an instance of Internet Explorer that looks like this:

Internet Explorer

Not too bad, huh? In our sample script, we pause for 10 seconds and then replace our old message with a new message, one that informs the user that their logon script has completed. We pause for 5 more seconds, and then dismiss our instance of Internet Explorer.

If you want to get a little fancier, you can do a couple things. In the revised script we’ll show you momentarily, we use the WMI class Win32_DesktopMonitor to determine the current video resolution (e.g., 1024x768). We then use some simple math to position the IE window in the middle of the screen. For example, if our screen is 1024 pixels wide, we subtract 400 (the width of our Internet Explorer window) from 1024. We divide that number by two, leaving us with the pixel position for the left side of our window. Repeating this trick with the display height (768) gives us the pixel position for the top of our window, and thus centers our dialog box on screen. Here’s the code that gets the screen width and height:

strComputer = "."
Set objWMIService = GetObject("Winmgmts:\\" & strComputer & "\root\cimv2")
Set colItems = objWMIService.ExecQuery("Select * From Win32_DesktopMonitor")
For Each objItem in colItems
    intHorizontal = objItem.ScreenWidth
    intVertical = objItem.ScreenHeight
Next

And here are the two lines of code that position the window on screen:

objExplorer.Left = (intHorizontal - 400) / 2
objExplorer.Top = (intVertical - 200) / 2

Note. The preceding code is really designed for computers that have only a single monitor; things get a bit more complicated on a multi-monitor system, especially if one of those monitors is turned off. For now, we’ll assume a single monitor; we’ll deal with the multi-monitor issue somewhere down the road.

In addition to centering the Internet Explorer window, we reinforce the fact that the user needs to wait for a moment by setting the cursor to an hourglass. That’s done with this line of code:

objExplorer.Document.Body.Style.Cursor = "wait"

Later in the script we set the cursor to default, which dismisses the hourglass and brings back the standard arrow cursor.

Here’s what our new and improved script looks like:

On Error Resume Next

strComputer = "."
Set objWMIService = GetObject("Winmgmts:\\" & strComputer & "\root\cimv2")
Set colItems = objWMIService.ExecQuery("Select * From Win32_DesktopMonitor")
For Each objItem in colItems
    intHorizontal = objItem.ScreenWidth
    intVertical = objItem.ScreenHeight
Next

Set objExplorer = CreateObject _
    ("InternetExplorer.Application")

objExplorer.Navigate "about:blank"   
objExplorer.ToolBar = 0
objExplorer.StatusBar = 0
objExplorer.Left = (intHorizontal - 400) / 2
objExplorer.Top = (intVertical - 200) / 2
objExplorer.Width = 400
objExplorer.Height = 200 
objExplorer.Visible = 1             

objExplorer.Document.Body.Style.Cursor = "wait"

objExplorer.Document.Title = "Logon script in progress"
objExplorer.Document.Body.InnerHTML = "Your logon script is being processed. " _
    & "This might take several minutes to complete."

Wscript.Sleep 10000

objExplorer.Document.Body.InnerHTML = "Your logon script is now complete."

objExplorer.Document.Body.Style.Cursor = "default"

Wscript.Sleep 5000

objExplorer.Quit

Still not fancy enough for you? Well, another way to spice things up is to include an animated .GIF in your InnerHTML. For example, this line of code displays an animated .GIF as well as a message:

objExplorer.Document.Title = "Logon script in progress"
objExplorer.Document.Body.InnerHTML = "<img src='file:///C:\Scripts\watch.gif'> " & _
    "Your logon script is being processed. This might take several minutes to complete."

The end result:

Internet Explorer

It might not qualify as art, but we think it does qualify as doing “…something interesting while the code executes.” And, remember, you can change the picture alignment, you can change the font size and color -- you can pretty much do anything HTML allows you to do.

Note. If you want to do something really interesting while your code executes, visit Dr. Scripto’s Fun Zone and learn how you can incorporate Microsoft Agent technology into your scripts.

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • Hey script guy,

    Apparently when a user closes out the progress status Internet browser, it throws the error "the object invoked has disconnected from it clients." and the script exits out?

    Is there any way to to have a new browser session open when the browser window is closed. or at least completete the script itself.

    Please help...

    I do that if I incorpate the Documeent.Writeln method, it doesn't throw the object invoked has disconnected from it clients error?

    Any suggestions?

    bjDocument.Writeln "<html><head><title> >>> Status Window <<< </title></head>"

    objDocument.Writeln "<body <body STYLE=""font:14 pt arial; color:white;" & _

    " filter:progid:DXImageTransform.Microsoft.Gradient(GradientType=0, StartColorStr='#000000', EndColorStr='#0000FF')"">"

    objDocument.body.style.cursor = "Wait" <--

    objDocument.Writeln "<p><B>Collecting Folder Sizes... If IE seems hung, give it a moment...<br></p>"

    objDocument.Writeln "</B><i>If Explorer window is closed the script will terminate.</i><br>"

    objDocument.Writeln "<br>Please be patient...<br>"

    ' ***************************

    CODE HERE

    ' ***************************

    'Completes HTML code for status window and closes it.

    objDocument.Writeln "<br>Finished!"

    objDocument.body.style.cursor = "default" <-- Sets curser back to default.

    objDocument.Writeln "</body></html>"

    objDocument.Writeln()

    objDocument.Close

  • when trying to run this code on some win7 machines with UAC enabled, this error message is returned:  ActiveX component can't create object: 'InternetExplorer.Application' for the line "Set objExplorer = CreateObject ("InternetExplorer.Application")".

    what security setting should be changed to allow this to run even though UAC is enabled?

  • please respond to the request for details under, this is something I've seen on several machines: all deployed through WDS using the same image and getting the same GPOs applied... If more details are required for debugging this issue, please let me know.

  • This actually opens 2x IE windows, but only one of them is closed 'objExplorer.Quit' is called. I'm using Windows 8 Pro and IE10.

  • How would I prevent the user from closing the 'new' IE window before my processing is done?


  • Thanks Scripting guy! Learning more and more from your pages these days!

    And if the script is to ignore the closed - probably checking to see if the page is alive or 'on error resume next' will work.

    This is where my script flaked when that window closed - otherwise it is helpful to kill the script : )