Introduction to Error Handling

By The Microsoft Scripting Guys

Sesame Script

Welcome to Sesame Script, the column for beginning script writers. The goal of this column is to teach the very basics of Windows scripting for system administration automation. We’ll provide you with the information you’ll need to begin reading and understanding scripts and to start modifying those scripts to suit your own needs. If there’s anything in particular about scripting you’re finding confusing, let us know; you’re probably not alone.

Check the Sesame Script Archives to see past articles.

On This Page

What’s the Problem?
Troubleshooting vs. Error Handling
Error Types
Don’t Stop Now
Not Complete Denial
Be Explicit
That’s It?

What’s the Problem?

Have you ever worked on a team where one person always seems to be causing problems? If anything ever goes wrong, it can typically be linked to that person in some way. Sometimes it might not even be this person’s fault (not entirely, anyway), but this particular person just always turns out to be the scapegoat. Believe it or not, the Scripting Guys have someone like that, too (but Dean doesn’t like to talk about it, so we won’t mention that it’s him). Things happen, mistakes are made, and there’s always one person to point a finger at.

The problem with writing scripts is that it’s hard to blame anyone else when your script doesn’t work the way you want it to. (Well, you could blame Dean; he may very well have had something to do with it.) But, most of the time, you wrote the script, or modified someone else’s script, and now it just doesn’t work. What do you do now? You could spend several days contemplating the unfairness of the world and cursing the day you ever heard of scripting, or you could simply do some troubleshooting.

Troubleshooting vs. Error Handling

We’re going to talk about troubleshooting and error handling, so we should probably start by explaining what the difference is between the two. Simply put, troubleshooting is figuring out what went wrong; error handling is knowing what could go wrong and dealing with it ahead of time. We’re not really going to distinguish between the two in this discussion, we’re just going to get you started with a couple of simple techniques you can use to get out of trouble and stay out.

Error Types

There are three types of errors: syntax, runtime, and logic.

Syntax Errors

Syntax errors are usually the result of an incorrectly used keyword. Here are a couple of examples:

intNumber = 2
If intNumber = 2 Then
    Wscript.Echo intNumber
Edn If

intNumber = 2
If intNumber = 2
    Wscript.Echo intNumber
End If

In the first example, take a look at the closing End If statement. End is spelled Edn. VBScript doesn’t know what Edn means, so it thinks the If statement doesn’t have an End If and returns an error. In the second example we left the Then keyword off of the If Then statement. Again, VBScript is expecting a Then but doesn’t see one, so it will return an error.

VBScript catches syntax errors before it tries to run the script and displays an error message if any of these errors are found. When you type cscript test.vbs at the command prompt, VBScript will look at the script and determine whether all the If’s have matching Then’s and that all other syntax issues are okay. Only if they are will it try to run the script.

Tip: Because syntax errors are checked before a script runs, a safe way to check for syntax errors is to put Wscript.Quit as the first line in your script, like this:

Wscript.Quit
intNumber = 2
If intNumber = 2
    Wscript.Quit intNumber
End If

You might have a script that is designed to delete files or change properties in Active Directory. Maybe you’re still working on your script but you want to check and make sure your syntax is correct before you actually delete or change anything. Adding Wscript.Quit to the beginning of your script is an easy way to do this. When you try to run the script, it will be checked for syntax errors. If errors are found, they’ll be output to the screen and the script will never run. If there aren’t any syntax errors the script will run, but the very first line ends the script and no other lines are executed. You’ve just safely tested the syntax of your script without actually running any of the script code.

Runtime Errors

Once you get through the syntax checks with no errors VBScript tries to run the script. At this point you might still get an error, but this time it’s a runtime error, meaning the error occurs when the script is running. An example of a runtime error would be trying to connect to a computer that doesn’t exist. VBScript has no way of knowing this ahead of time; the script needs to run and actually attempt to connect to the computer before it finds out there is no computer by that name (or it’s offline, or whatever). At that point you’ll receive an error message letting you know something went wrong.

Logic Errors

Logic errors are usually the most difficult errors to find. With a logic error, VBScript decides the script looks okay, the script runs and completes with no problems, but you don’t get the results you expect. Here’s an example of how that could happen:

intNumber = 2
If intNumber > 0 Then
    Wscript.Echo "Greater than zero"
ElseIf intNumber > 1 Then
    Wscript.Echo "Greater than one"
ElseIf intNumber > 2 Then
    Wscript.Echo "Greater than two"
End If

In this example, we’ve set intNumber equal to 2. When you go into the If statement, you might expect to receive the message “Greater than one.” And when you look at the choices that might make sense: we check to see if intNumber is greater than 0, which it is. Then we check to see if it’s greater than 1, and yes, 2 is greater than 1. Finally we check to see if it’s greater than 2, which it’s not. So our message should be “Greater than one,” right? Nope. The way an If-ElseIf statement works is that the first If statement will be checked: is intNumber greater than 0? If it is, the message “Greater than zero” will be echoed to the screen, and you’ll go straight to the End If statement. The ElseIf statements will never happen.

As you can see, there’s nothing actually wrong with this script, it does exactly what it’s supposed to; it just doesn’t do exactly what you want it to. You have an error in the logic of your script, or the way the script works.

Don’t Stop Now

Have you ever noticed how good people can be at denial? “I’m not going bald, I just have a high forehead.” “No, that wasn’t my child kicking the back of your seat and talking all through the movie.” “There are no errors in my script, there’s something wrong with the computer.”

We can’t help you with the first two, but we hear about that third one a lot. And more often than not it’s due to one simple little statement that appears at the very top of many scripts:

On Error Resume Next

This statement is VBScript in denial. With this statement at the beginning of your script, the only errors you’ll ever see are syntax errors. Once a script with an On Error Resume Next statement in it actually manages to start running there’s no stopping it. For example, here’s a script that echoes a number representing the month in a given date:

Wscript.Echo Month("February 1, 2006")

If you run this script, it will return a value of 2, because, obviously, February is the second month of the year. But as many of us may remember from our childhood, or even from last February, the word “February” can be kind of hard to spell - it’s easy to leave out that first “r”:

Wscript.Echo Month("Febuary 1, 2006")

In this case, we haven’t provided the Month function with a valid date. Therefore, when you run this script you’ll receive the following error message:

C:\Scripts\test.vbs(2, 1) Microsoft VBScript runtime error: Type mismatch: '[string: "Febuary 1"]'

It’s now pretty easy to see that we have a problem with the date we entered, namely that it’s not a date.

Note: If this were an article on debugging, this is where we’d point out that the error message says the type mismatch is because you were supposed to enter a string. But “Febuary 1” is a string, so now what? Well, if you don’t immediately notice your typo, your next step would be to check the VBScript Language Reference, where you’ll find out that “The date argument is any expression that can represent a date.” But since this article is on finding and avoiding errors and not fixing them, we won’t mention that here.

What does all this have to do with being in denial? Well, try this:

On Error Resume Next
Wscript.Echo Month("Febuary 1, 2006")

What does this script return? Absolutely nothing. Because we haven’t passed the Month function a valid date, it can’t return anything. But we also don’t get an error. The On Error Resume Next statement has caused the script to continue on after encountering an error. This might, at first, seem to be a real problem. Why in the world wouldn’t you want to know if there’s an error in your script? Well, how about this:

arrDates = Array("01-01-06", "02-01-06", "03-01-06", "99-99-06", "05-01-06")

For Each dtDate in arrDates
    Wscript.Echo Month(dtDate)
Next

In this example we have an array of dates. In real life this could be a row of dates read in from a text file or an Excel spreadsheet. In any set of information, there’s always the possibility that some of the data will be invalid. If someone happens to enter an invalid date, like we did in our array, the Month function will return an error when it reaches that date and the script will stop:

1
2
3
C:\Scripts\test.vbs(6, 5) Microsoft VBScript runtime error: Type mismatch: 'dtDate'

However, if we add On Error Resume Next to the beginning of our script, the script hits the error, ignores it, and continues to run:

1
2
3
5

As you can see, On Error Resume Next can come in handy. At the same time, however, it can mask problems and give unexpected results, so always be careful when you use this method of error-handling. We also want to point out - pay attention now, this is very important: if you’re ever having trouble with a script, the very first thing you’ll want to do is comment out On Error Resume Next. It’s very difficult to diagnose a problem when your script is denying that there is one.

Not Complete Denial

You might not want to completely ignore errors. In the preceding script, you might not want the script to come to a crashing halt when it gets to an invalid date, but you also might not want to just skip right by it. Maybe you want to know that there is invalid information in your data set. But if you put On Error Resume Next in your script and ignore errors, how do you know they happened? Simple: just ask.

VBScript provides an object called the Err object. When an error occurs in a VBScript method that method returns an error number that you can access through the Number property of the Err object. So if the Number property is anything except zero, an error has occurred. Here’s our revised script:

On Error Resume Next

arrDates = Array("01-01-06", "02-01-06", "03-01-06", "99-99-06", "05-01-06")

For Each dtDate in arrDates
    Wscript.Echo Month(dtDate)
    If Err.Number Then
        Wscript.Echo "Date " & dtDate & " is invalid"
        Err.Clear
    End If
Next

As you can see, immediately after we call the Month function we check the value of Err.Number in an If statement. If the value is anything but zero, we know we had an invalid date and we display that fact. Now when we run the script, our output looks like this:

1
2
3
Date 99-99-06 is invalid
5

Always Be Clear

There’s one very important thing to note about the Err object. Take another look at our previous script:

On Error Resume Next

arrDates = Array("01-01-06", "02-01-06", "03-01-06", "99-99-06", "05-01-06")

For Each dtDate in arrDates
    Wscript.Echo Month(dtDate)
    If Err.Number Then
        Wscript.Echo "Date " & dtDate & " is invalid"
        Err.Clear
    End If
Next

Inside the If statement, after we echo back the invalid date, we call the Err.Clear method. This is critical to the success of your error handling. The way the Err object works is that, when an error occurs, the Err object contains all the information about that error. Think of the Err object as a basket. We’ve put something into the basket. But the next time we go through our For loop to check for the next date in the array, our basket is still full, which means the Err object still contains the error from last time. So you always want to “empty the basket,” or clear the Err object, before you run another method, otherwise you might end up with a full basket when you’re expecting an empty one. And just in case our wonderful basket metaphor wasn’t crystal clear, look what happens when we don’t call Err.Clear:

1
2
3
Date 99-99-06 is invalid
5
Date 05-01-06 is invalid

The Err object still had an error in it when we checked for our valid date of 05-01-06, so even though we echoed the correct month value, we also echoed back that we had another error. So don’t forget Err.Clear!

Be Explicit

This is an area we discussed in a previous article, but we can’t discuss error handling without mentioning it: the Option Explicit statement. Let’s go back to our earlier example:

intNumber = 2
If intNumber = 2 Then
    Wscript.Echo intNubmer
End If

When you run this script you’re probably expecting it to echo back 2. What it will do instead is echo nothing. If you look closely, you can see that in the Wscript.Echo statement, our variable is spelled incorrectly, inNubmer rather than intNumber. This doesn’t produce an error. VBScript simply thinks you’re using a different variable, which you never actually gave a value so it defaulted to nothing. This type of error can be difficult to spot (even removing an On Error Resume Next statement won’t help you) because there’s no error for VBScript to report. One way to guard against this type of error is to include the Option Explicit statement:

Option Explicit

intNumber = 2
If intNumber = 2 Then
    Wscript.Echo intNubmer
End If

Now when you run the script you’ll receive an error message:

C:\Scripts\test.vbs(3, 1) Microsoft VBScript runtime error: Variable is undefined: 'intNumber'

Wait a minute, intNumber isn’t the problem, the variable that isn’t spelled correctly is intNubmer. Why am I getting an error on the variable I want? Because Option Explicit tells VBScript to display an error for any variable that hasn’t been explicitly declared (get it, explicitly, Option Explicit?) with a Dim statement. That means every single variable you use in your script, including object references, must be declared before you can use it, like this:

Option Explicit

Dim intNumber

intNumber = 2
If intNumber = 2 Then
    Wscript.Echo intNubmer
End If

Now when you run your script you get an error message that will actually help you:

C:\Scripts\test.vbs(7, 5) Microsoft VBScript runtime error: Variable is undefined: 'intNubmer'

As with all good remedies there are side-effects to Option Explicit. As we already saw, we might get errors on variables that are perfectly fine because we forgot to declare them with a Dim statement. If you have a lot of variables in your script this can get very cumbersome. Some people go too far the other direction and leave in Dim statements for variables they don’t even use. This, too can clutter up your script and make it hard to read, so try to clean up after yourself. There’s nothing like a nice, neat script to get you through the day.

That’s It?

There is much more to error handling than the little bit we’ve shown you here in this article. But we’re tired of working now, so this is all you get.

(Oops, our manager just walked by and saw that.) No, really, just kidding, we never get tired of working. And we’d never leave our devoted readers without making sure we’d provided as much information as we possibly could. But what we have done here is give you a quick overview of error-handling, and shown you just a few types of errors you might encounter. For more in-depth information and some intermediate-to-advanced error-handling techniques, take a look at To Err is VBScript. And of course, there’s always the handy Windows 2000 Scripting Guide, loaded with information.

If you’re still stuck, blame Dean. That always works for us.