Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Schongar P.VBScript unleashed.1997

.pdf
Скачиваний:
45
Добавлен:
23.08.2013
Размер:
1.59 Mб
Скачать

Notice that I used the ampersand (&) to concatenate the strings in the MsgBox calls. This behaves differently than the plus sign (+) because it causes the VBScript compiler to convert the expressions on both sides of the ampersand to strings. The plus sign does not perform this datatype conversion, so you have to use the CStr function to convert the expressions to strings.

The Raise Method

The Raise method enables you to create runtime errors within your scripts. This method really is designed to allow ActiveX component developers to create a runtime error condition within their component's code. These then are trapped by the script, as described in the section "Specifying Error Trapping," earlier in this chapter. Because the Err object is a generic object, however, the Raise method also can be used in VBScript code. One of the examples presented later in the chapter (in the section titled "Using the Raise Method") demonstrates using the Raise method in a subroutine to immediately cause an error condition.

The Raise method is invoked with this code:

Err.Raise number[,source[, description[, helpfile[, helpcontext]]]]

The values specified as parameters will be assigned to the respective properties of the Err object. The number parameter is the error number to be raised. The source parameter is a string that specifies the process that generated the error. In Internet Explorer, if this parameter is left empty, the Err.Source property value is VBScript. The description is a string describing the error condition. The helpfile and helpcontext parameters generally aren't used within VBScript code, but they specify the name of a local Help file and a context ID within that Help file. The specified Help file is displayed if the user presses f1 from within the default VBScript Error dialog.

The only required argument is number. If you don't specify the other values, however, the Err object's properties retain the values that were present in the object when you invoked the Raise method. You can use the Clear method described earlier to clear these properties before invoking the Raise method.

Looking at Examples of Error Handling

This section provides two sample VBScript pages. The first demonstrates the handling of runtime errors within a script. It uses the On Error Resume Next statement described earlier to trap runtime errors. The second example illustrates the use of the Err object's Raise method to programmatically create runtime errors. Although this might seem like a sadistic action for a programmer to take, the example presented shows how doing so in subroutines actually can be useful.

Trapping Runtime Errors

This example demonstrates how to use the On Error Resume Next statement to trap runtime errors. Listing 10.1 shows the HTML code for the sample page. This section discusses what's going on in the VBScript code as it relates to error trapping.

Listing 10.1. HTML for the runtime error-trapping example.

<HTML>

<HEAD>

<SCRIPT LANGUAGE="VBScript">

<!--

Option Explicit

Sub window_onLoad()

Dim intTemp

On error resume next

intTemp = -1

MsgBox Left("Quick Brown Fox", cint(intTemp))

if Err then

MsgBox "Error: " & Err.description

Err.clear

end if

intTemp = 5

MsgBox Left("Quick Brown Fox", cint(intTemp))

if Err then

MsgBox "Error: " & Err.description

Err.clear

else

MsgBox "No error occurred!"

end if

end sub

-->

</SCRIPT>

<TITLE>Test Page</TITLE>

</HEAD>

<BODY>

</BODY>

</HTML>

Starting with the first <SCRIPT> tag, the first line of VBScript code (following the start of the HTML comment), is the Option Explicit directive, discussed earlier in this chapter. This prevents you from using a variable without declaring it first. You then come to the definition of the onLoad event for the main window. This is where all the code for this example is executed.

The first line of code within this event defines a variable named intTemp. This is followed by the On Error Resume Next statement. Then the value -1 is assigned to the intTemp variable, and the code attempts to use this variable as a parameter for the Left() function. Because the expression Left(string, -1) is invalid, a runtime error is produced. The next line of code following the MsgBox statement is where you check for the occurrence of a runtime error. The statement If Err then is equivalent to If Err.value > 0 then, so any value other than 0 in the Err object's value property causes this statement to evaluate to True.

A message box then is displayed, showing a description of the error. The Err object then is cleared using the Clear method. This ensures that any other references to the Err object's properties don't inadvertently use old property values.

After end if, the value of intTemp is set to 5. The same MsgBox statement is attempted again. This time, however, a valid value is passed to the Left() function, and no runtime error occurs. The Else portion of the code is executed and a box with the No error occurred! message is displayed.

Enter the HTML into the Control Pad or Notepad, save it to a file, and then open the file with the Internet Explorer. You should see a total of three message boxes: one for the runtime error, one with the message Quick, and the final one with the message No error occurred!

Using the Raise Method

The final example of this chapter illustrates how you can use the Raise method within your VBScript code. Although this method might not always be the best way to control the flow of your code, it can prove useful at times. Listing 10.2 contains the HTML code for this example.

Listing 10.2. HTML for the Raise method example.

<HTML>

<HEAD>

<SCRIPT LANGUAGE="VBScript">

<!--

Option Explicit

Sub TestRaise(blnRaiseError)

if blnRaiseError then

Err.Raise 9000, "TestRaise", "Error from TestRaise"

end if

MsgBox "Error not called for"

end sub

Sub window_onLoad()

on error resume next

call TestRaise(1)

if Err then

MsgBox "Error occurred: " & Err.description

Err.clear

end if

call TestRaise(0)

if Err then

MsgBox "Error occurred: " & Err.description

Err.clear

end if

end sub

-->

</SCRIPT>

<TITLE>Testing Raise Method</TITLE>

</HEAD>

<BODY>

</BODY>

</HTML>

This code is very simple. The procedure TestRaise takes a single parameter, blnRaiseError. If this variable's value is greater than 0, the Raise method is invoked with some hard-coded values. This causes the procedure to immediately exit back to the calling routine. If the value is 0, a message box is displayed.

The code for the onLoad event of the main window is where you call the TestError procedure. The On Error Resume Next statement is used to trap the errors. Then TestError is called with a parameter of 1. This causes the Raise method to be invoked and the If Err then block to be entered, displaying the appropriate message box.

The code then calls TestError again, but this time with a parameter of 0. The Raise method is not invoked and the message box within the TestError procedure is displayed. No error condition exists, so when execution returns to the onLoad event, no error message box is displayed.

After this page is loaded into Internet Explorer, you see two message boxes. The first is the error message dialog stating that Error occurred: Error from TestRaise. The second is the message box within TestRaise that states Error not called for.

Review

This chapter covered the basics of error handling within VBScript code. The best way to experience how errors are handled within a particular host application (such as Internet Explorer) is to experiment with error-handling code, such as that provided in Listings 10.1 and 10.2.

From this chapter, you move on to learn how to optimize your VBScript code and then debug your code and create dynamic Web pages. By the time you finish reading this part of the book, you'll have more than enough background to proceed through the final two parts of the book.

Chapter 12

Debugging

by Keith Brophy and Timothy Koets

CONTENTS

Handling VBScript Errors

Syntax Errors: Say What You Mean!

Semantic Errors: Mean What You Say!

Using Simple Debugging Techniques

Using the MsgBox Statement

Using the OnErrorResumeNext Statement

Using the Err Object

Taking the Err Object Further

Using Advanced Debugging Techniques

Tracing Your Code Using the Message Box

Saturating Your Code with the Message Box

Watching Your Code Using Variables and the Message Box

Breaking Apart Complex Statements to Find Bugs

Using Other Tools to Help You with the Debugging Task

Using VBScript Versus Traditional Debugging Environments

Using Visual Basic to Debug VBScript Applications

Using Visual Basic 4.0 Trace Capabilities

Debugging VBScript Code Within Visual Basic

Handling HTML Errors

Making Sure the Bugs Are Dead

Creating Your Own Debug Window for Tracing

Building Your Own Tracing Routines

Looking at a Sample Variable Analysis Routine

Looking at More Reasons Why VBScript Can Be Tough to Debug

The Moral of the Story

Review

If you have been a programmer for very long, you probably realize that writing programs is sometimes the easy part of software development. It's getting the bugs out that can be the real challenge! Judgment is needed to effectively sift through many hundreds or thousands of possible causes of a problem and hone in on a specific bug. At the same time, a great deal of logical, objective analysis must be applied to a debugging problem to scientifically pinpoint a bug and prove its existence. As a result, the process of bug-hunting often requires a special focus and concentration seldom encountered in other aspects of life. And, as anyone with experience debugging an application will quickly realize, the frustration involved can be enormous! The good news is that problem-solving techniques and top-notch tools can make this process much easier. The not-so-good news, however, is that such top-notch tools do not come with VBScript. Nevertheless, the tips and techniques suggested in this chapter will go a long way toward minimizing your debugging pitfalls.

Handling VBScript Errors

In order to effectively debug applications, you first must learn a bit about what errors are, what forms they take, and how to handle them when they occur. Once you know how to effectively handle them, you will be more effective in recognizing and preventing them. This first section gives you the background you need to learn about debugging techniques. The techniques themselves are presented in the next section of this chapter.

Unfortunately, VBScript offers little in the way of sophisticated debugging tools and error handling when your program is running. Most commercial language products, including Visual Basic 4.0, offer a development environment that is tremendously helpful when you're debugging programs. Later in this chapter, you'll learn more about those capabilities and what debugging tools VBScript lacks. But first, you should examine what VBScript does provide when errors occur. To do this, you should take a look at the various types of errors that can occur in a VBScript program.

Syntax Errors: Say What You Mean!

Errors come in a variety of shapes and sizes. The easiest ones to picture and correct are simple typing or language-usage errors in your VBScript code. For example, consider what would happen if you mistakenly type

Dimwit C

instead of

Dim C

in order to declare a variable named C. Because the word Dimwit is not part of the VBScript language or syntax, the first statement can't be processed. This kind of error commonly is called a syntax error.

Obviously, if you have a syntax error, your program is not going to work as intended. Fortunately, a program with a syntax error normally won't even run, and the problem can be spotted right away! Such stubborn behavior is fortunate, because the sooner you find a problem, the better. You'd probably rather have your program go "on strike" immediately than have the problem pop up when a user is interacting with your script or, worse yet, when your program gives your user an incorrect result that he's not even aware of!

So how does VBScript respond to a syntax error? Suppose that you have the statement

Dim c, c, c

This statement, too, contains a syntax error. This time, the error consists of an illegal duplicate definition instead of an incorrectly typed keyword. This statement is not legal according to the rules of VBScript, because a variable name can be used only once; here, it is defined three times in a row. When you attempt to load the page containing this program into the browser, you are greeted with the message shown in Figure 12.1.

Figure 12.1 : A syntax-checking script error message.

This particular error is identified as soon as the page is loaded in the browser, but other syntax errors might not be caught until after the Web page is loaded. Suppose that a certain code statement is carried out only after a specific button is clicked. In the script event-handler routine associated with that button, suppose that a series of other calculations precedes the statement

a = b / c

Now, assume that the variable c already has been computed before this statement and that the value stored in c varies from one

calculation to another. This statement might work perfectly well for the first several times the button is clicked. If, however, the value of c ever turns out to be 0, this statement fails. Because the computer is unable to divide by 0, VBScript generates a message box similar to the one in Figure 12.1. This brings your program to a screeching halt.

NOTE

When you are presented with the runtime error message from the Internet Explorer browser, you have the option of enabling a checkbox to suppress notification of future runtime errors. If you enable the Ignore further script errors on this page checkbox, notification of future errors in other scripts on the page is suppressed. Loading of the specific script that caused the problem still is halted when errors occur.

These are just two examples of many possible errors that can be detected when VBScript tries to run your program. The errors shown in these examples are referred to as runtime errors. Hopefully, your user never sees any runtime errors. Ideally, you would write perfect, error-free code! However, given the complexity of programming, the odds of producing a perfect program are slim. Therefore, you must be able to thoroughly test your programs to remove all their problems before you turn them over to your users. You also can take steps when writing your code to make it more robust if a runtime error occurs during development.

NOTE

When a browser runs your VBScript code embedded in HTML, it does so by passing the VBScript statements to a separate component of software called the VBScript Interpreter. This interpreter checks and runs the VBScript code.

Unfortunately, no standard VBScript interactive development environment exists from Microsoft to make the debugging task easier. This makes the task of error-proofing your programs a considerable challenge. VBScript does provide some help in recovering from errors and pinning them down, however. You can write code that helps a program robustly continue after an error occurs. The On Error Resume Next statement serves this purpose. After an error occurs, a convenient source of information called the Err object is available for use in your code as well. With the Err object, you can write program logic that prints error information or takes a code path based on an analysis in code of what error occurred. These techniques for dealing with runtime errors are covered in "Using Simple Debugging Techniques" later in this chapter. But first, take a look at another type of error.

Semantic Errors: Mean What You Say!

By now, you might be feeling a little more at ease, comforted by the idea that there is some support in the VBScript language to help you handle errors. Don't get too comforted, though! First of all, VBScript support for runtime errors might help you handle them, but it won't help you prevent or eliminate them. Second, semantic errors can pose an even bigger problem than syntax errors. A semantic error is an error in meaning (that is, you fail to write the program to achieve the purpose you intended). Suppose that you want to add a 4 percent sales tax to the cost of an item. You provide the following code statement:

total = orig_price + orig_price * 4

4 is used here in place of .04. The result is that this incorrect statement doesn't add 4 percent to your total sale, but it does add four times the cost of your item to your total sale! This is clearly an error. As far as the VBScript Interpreter can tell, however, this statement is fine. VBScript doesn't know what a sales tax rate is. It obediently carries out the calculation you give it.

With a semantic error, the problem rests squarely on your shoulders. VBScript, or any other language for that matter, is not able to automatically highlight this kind of an error for you. Instead, after noticing an incorrect result, you must work backward until you hone in on the problem. Semantic problems do not directly cause runtime errors; they just lead to bad results. And although

bad results might suggest that you have a problem, they don't tell you where it is. Often, you must trace through your program line by line, ensuring that each line is correct and produces valid results before proceeding to the next line.

Some languages offer support for this kind of tracing. In the case of VBScript, however, you must put together your own traces. Trace tactics that can be used to address errors are discussed in the following section, and there you'll get a closer look at runtime error-handling techniques you can use to tackle syntax errors. For now, recognize that it is not too important that you know the textbook description of semantic versus syntax errors. It is important, however, that you are aware of the techniques available for dealing with them. You also should realize that the most important tools for debugging-patience and persistencecan be provided only by you.

Using Simple Debugging Techniques

Now that you have a feel for the type of error support in VBScript, it's time to observe it in action. The program used to illustrate debugging principles throughout this chapter is the Pace-Pal program. Pace-Pal is a standard HTML Web page with embedded VBScript code. The program is shown in Figure 12.2.

Figure 12.2 : The Pace-Pal program.

Pace-Pal enables you to specify a distance in miles or kilometers and a time in minutes/seconds format. (Hours also can be provided optionally if you're willing to run that long!) With this information, a pace per mile can be calculated. If you run a 26.2 mile race (10k) in three hours and supply that information to Pace-Pal, for example, Pace-Pal calculates that you averaged 6:52-minute miles. This scenario is shown in Figure 12.2.

Pace-Pal does its job very nicely when it has perfect, well-mannered, never-make-a-mistake users. It runs into problems, however, when faced with the more typical user who occasionally makes mistakes. Specifically, Pace-Pal does a poor job of handling nonstandard input.

Pace-Pal can derive a 10k pace from a time of 37:12 faster than you can blink an eye. But if you accidentally type 37:12AA rather than 37:12 for the time, disaster strikes. Pace-Pal's code is not constructed to deal with a time in such a format. The code doesn't check the data integrity. Instead, it tries to process the data, causing the VBScript Interpreter to attempt the impossible with the current statement. An attempt is made to carry out a calculation based on character data. The poor VBScript Interpreter is left holding the bag, asked to carry out a statement that makes no sense and will lead to an incorrect result! Needless to say, the interpreter balks, tossing up the famed runtime error window. Figure 12.3 shows the runtime error window generated after Pace-Pal attempts to process a time of 37:12AA.

Figure 12.3 : Bad input data causes a runtime error in the Pace-Pal program.

VBScript is nice enough to clue you into the problem. The error message displayed tells you that the problem is related to an attempted type conversion that is illegal under the rules of VBScript. Unfortunately, VBScript doesn't tell you where this error occurred. And, even worse from the user's point of view, VBScript halts execution of the script because it detected problems there. If you go back and specify good input and click the Display Pace button, nothing happens. Until the page is reloaded, VBScript considers this a bad script and doesn't process any of it.

In certain cases, VBScript does provide you with the location of statements that contain errors. In many cases, fundamental flaws in language definition can be detected and pointed out with line-number information when a page is loaded. This is the case with the error shown in Figure 12.3. More subtle errors, or errors that only show up when there are certain data conditions, cannot be predetected. The 37:12AA bad-data-induced error falls into this category. Debugging then becomes considerably more complicated, because half the battle is simply determining which statements caused VBScript to balk.

Take a look at the code in Listing 12.1, for example. This is just one section of the rather lengthy Pace-Pal program. Even after you've gotten a hint that the culprit statement lurks somewhere in this subset of the code, does it easily jump out at you?

NOTE

The source file for the Pace-Pal program is located on the accompanying CD-

ROM in the pace-pal.htm file.

Listing 12.1. Source code that contains an error.

Function ConvertStringToTotalSeconds (ByVal sDuration)

'

--------------------------------------------------------------------------

' Purpose: Takes HH:MM:SS format string and converts to total seconds

'

--------------------------------------------------------------------------

Dim iPosition

' Position of

":" seperator

Dim vHours

' Number

of hours required

Dim vMinutes

' Number

of minutes

required

Dim vSeconds

' Number

of seconds

required

'Start working from right of string, parsing seconds

sMode = "Seconds"

'Get leftmost time component

iPosition = InStr(sDuration, ":")

If iPosition = 0 Then

' No more time info, assume time info just in ss format

vSeconds = sDuration

Else ' More time info is in string

' Store first portion in hours for now, assume hh:mm:ss format