- •Using Your Sybex Electronic Book
- •Acknowledgments
- •Contents at a Glance
- •Introduction
- •Who Should Read This Book?
- •How About the Advanced Topics?
- •The Structure of the Book
- •How to Reach the Author
- •The Integrated Development Environment
- •The Start Page
- •Project Types
- •Your First VB Application
- •Making the Application More Robust
- •Making the Application More User-Friendly
- •The IDE Components
- •The IDE Menu
- •The Toolbox Window
- •The Solution Explorer
- •The Properties Window
- •The Output Window
- •The Command Window
- •The Task List Window
- •Environment Options
- •A Few Common Properties
- •A Few Common Events
- •A Few Common Methods
- •Building a Console Application
- •Summary
- •Building a Loan Calculator
- •How the Loan Application Works
- •Designing the User Interface
- •Programming the Loan Application
- •Validating the Data
- •Building a Math Calculator
- •Designing the User Interface
- •Programming the MathCalculator App
- •Adding More Features
- •Exception Handling
- •Taking the LoanCalculator to the Web
- •Working with Multiple Forms
- •Working with Multiple Projects
- •Executable Files
- •Distributing an Application
- •VB.NET at Work: Creating a Windows Installer
- •Finishing the Windows Installer
- •Running the Windows Installer
- •Verifying the Installation
- •Summary
- •Variables
- •Declaring Variables
- •Types of Variables
- •Converting Variable Types
- •User-Defined Data Types
- •Examining Variable Types
- •Why Declare Variables?
- •A Variable’s Scope
- •The Lifetime of a Variable
- •Constants
- •Arrays
- •Declaring Arrays
- •Initializing Arrays
- •Array Limits
- •Multidimensional Arrays
- •Dynamic Arrays
- •Arrays of Arrays
- •Variables as Objects
- •So, What’s an Object?
- •Formatting Numbers
- •Formatting Dates
- •Flow-Control Statements
- •Test Structures
- •Loop Structures
- •Nested Control Structures
- •The Exit Statement
- •Summary
- •Modular Coding
- •Subroutines
- •Functions
- •Arguments
- •Argument-Passing Mechanisms
- •Event-Handler Arguments
- •Passing an Unknown Number of Arguments
- •Named Arguments
- •More Types of Function Return Values
- •Overloading Functions
- •Summary
- •The Appearance of Forms
- •Properties of the Form Control
- •Placing Controls on Forms
- •Setting the TabOrder
- •VB.NET at Work: The Contacts Project
- •Anchoring and Docking
- •Loading and Showing Forms
- •The Startup Form
- •Controlling One Form from within Another
- •Forms vs. Dialog Boxes
- •VB.NET at Work: The MultipleForms Project
- •Designing Menus
- •The Menu Editor
- •Manipulating Menus at Runtime
- •Building Dynamic Forms at Runtime
- •The Form.Controls Collection
- •VB.NET at Work: The DynamicForm Project
- •Creating Event Handlers at Runtime
- •Summary
- •The TextBox Control
- •Basic Properties
- •Text-Manipulation Properties
- •Text-Selection Properties
- •Text-Selection Methods
- •Undoing Edits
- •VB.NET at Work: The TextPad Project
- •Capturing Keystrokes
- •The ListBox, CheckedListBox, and ComboBox Controls
- •Basic Properties
- •The Items Collection
- •VB.NET at Work: The ListDemo Project
- •Searching
- •The ComboBox Control
- •The ScrollBar and TrackBar Controls
- •The ScrollBar Control
- •The TrackBar Control
- •Summary
- •The Common Dialog Controls
- •Using the Common Dialog Controls
- •The Color Dialog Box
- •The Font Dialog Box
- •The Open and Save As Dialog Boxes
- •The Print Dialog Box
- •The RichTextBox Control
- •The RTF Language
- •Methods
- •Advanced Editing Features
- •Cutting and Pasting
- •Searching in a RichTextBox Control
- •Formatting URLs
- •VB.NET at Work: The RTFPad Project
- •Summary
- •What Is a Class?
- •Building the Minimal Class
- •Adding Code to the Minimal Class
- •Property Procedures
- •Customizing Default Members
- •Custom Enumerations
- •Using the SimpleClass in Other Projects
- •Firing Events
- •Shared Properties
- •Parsing a Filename String
- •Reusing the StringTools Class
- •Encapsulation and Abstraction
- •Inheritance
- •Inheriting Existing Classes
- •Polymorphism
- •The Shape Class
- •Object Constructors and Destructors
- •Instance and Shared Methods
- •Who Can Inherit What?
- •Parent Class Keywords
- •Derived Class Keyword
- •Parent Class Member Keywords
- •Derived Class Member Keyword
- •MyBase and MyClass
- •Summary
- •On Designing Windows Controls
- •Enhancing Existing Controls
- •Building the FocusedTextBox Control
- •Building Compound Controls
- •VB.NET at Work: The ColorEdit Control
- •VB.NET at Work: The Label3D Control
- •Raising Events
- •Using the Custom Control in Other Projects
- •VB.NET at Work: The Alarm Control
- •Designing Irregularly Shaped Controls
- •Designing Owner-Drawn Menus
- •Designing Owner-Drawn ListBox Controls
- •Using ActiveX Controls
- •Summary
- •Programming Word
- •Objects That Represent Text
- •The Documents Collection and the Document Object
- •Spell-Checking Documents
- •Programming Excel
- •The Worksheets Collection and the Worksheet Object
- •The Range Object
- •Using Excel as a Math Parser
- •Programming Outlook
- •Retrieving Information
- •Recursive Scanning of the Contacts Folder
- •Summary
- •Advanced Array Topics
- •Sorting Arrays
- •Searching Arrays
- •Other Array Operations
- •Array Limitations
- •The ArrayList Collection
- •Creating an ArrayList
- •Adding and Removing Items
- •The HashTable Collection
- •VB.NET at Work: The WordFrequencies Project
- •The SortedList Class
- •The IEnumerator and IComparer Interfaces
- •Enumerating Collections
- •Custom Sorting
- •Custom Sorting of a SortedList
- •The Serialization Class
- •Serializing Individual Objects
- •Serializing a Collection
- •Deserializing Objects
- •Summary
- •Handling Strings and Characters
- •The Char Class
- •The String Class
- •The StringBuilder Class
- •VB.NET at Work: The StringReversal Project
- •VB.NET at Work: The CountWords Project
- •Handling Dates
- •The DateTime Class
- •The TimeSpan Class
- •VB.NET at Work: Timing Operations
- •Summary
- •Accessing Folders and Files
- •The Directory Class
- •The File Class
- •The DirectoryInfo Class
- •The FileInfo Class
- •The Path Class
- •VB.NET at Work: The CustomExplorer Project
- •Accessing Files
- •The FileStream Object
- •The StreamWriter Object
- •The StreamReader Object
- •Sending Data to a File
- •The BinaryWriter Object
- •The BinaryReader Object
- •VB.NET at Work: The RecordSave Project
- •The FileSystemWatcher Component
- •Properties
- •Events
- •VB.NET at Work: The FileSystemWatcher Project
- •Summary
- •Displaying Images
- •The Image Object
- •Exchanging Images through the Clipboard
- •Drawing with GDI+
- •The Basic Drawing Objects
- •Drawing Shapes
- •Drawing Methods
- •Gradients
- •Coordinate Transformations
- •Specifying Transformations
- •VB.NET at Work: Plotting Functions
- •Bitmaps
- •Specifying Colors
- •Defining Colors
- •Processing Bitmaps
- •Summary
- •The Printing Objects
- •PrintDocument
- •PrintDialog
- •PageSetupDialog
- •PrintPreviewDialog
- •PrintPreviewControl
- •Printer and Page Properties
- •Page Geometry
- •Printing Examples
- •Printing Tabular Data
- •Printing Plain Text
- •Printing Bitmaps
- •Using the PrintPreviewControl
- •Summary
- •Examining the Advanced Controls
- •How Tree Structures Work
- •The ImageList Control
- •The TreeView Control
- •Adding New Items at Design Time
- •Adding New Items at Runtime
- •Assigning Images to Nodes
- •Scanning the TreeView Control
- •The ListView Control
- •The Columns Collection
- •The ListItem Object
- •The Items Collection
- •The SubItems Collection
- •Summary
- •Types of Errors
- •Design-Time Errors
- •Runtime Errors
- •Logic Errors
- •Exceptions and Structured Exception Handling
- •Studying an Exception
- •Getting a Handle on this Exception
- •Finally (!)
- •Customizing Exception Handling
- •Throwing Your Own Exceptions
- •Debugging
- •Breakpoints
- •Stepping Through
- •The Local and Watch Windows
- •Summary
- •Basic Concepts
- •Recursion in Real Life
- •A Simple Example
- •Recursion by Mistake
- •Scanning Folders Recursively
- •Describing a Recursive Procedure
- •Translating the Description to Code
- •The Stack Mechanism
- •Stack Defined
- •Recursive Programming and the Stack
- •Passing Arguments through the Stack
- •Special Issues in Recursive Programming
- •Knowing When to Use Recursive Programming
- •Summary
- •MDI Applications: The Basics
- •Building an MDI Application
- •Built-In Capabilities of MDI Applications
- •Accessing Child Forms
- •Ending an MDI Application
- •A Scrollable PictureBox
- •Summary
- •What Is a Database?
- •Relational Databases
- •Exploring the Northwind Database
- •Exploring the Pubs Database
- •Understanding Relations
- •The Server Explorer
- •Working with Tables
- •Relationships, Indices, and Constraints
- •Structured Query Language
- •Executing SQL Statements
- •Selection Queries
- •Calculated Fields
- •SQL Joins
- •Action Queries
- •The Query Builder
- •The Query Builder Interface
- •SQL at Work: Calculating Sums
- •SQL at Work: Counting Rows
- •Limiting the Selection
- •Parameterized Queries
- •Calculated Columns
- •Specifying Left, Right, and Inner Joins
- •Stored Procedures
- •Summary
- •How About XML?
- •Creating a DataSet
- •The DataGrid Control
- •Data Binding
- •VB.NET at Work: The ViewEditCustomers Project
- •Binding Complex Controls
- •Programming the DataAdapter Object
- •The Command Objects
- •The Command and DataReader Objects
- •VB.NET at Work: The DataReader Project
- •VB.NET at Work: The StoredProcedure Project
- •Summary
- •The Structure of a DataSet
- •Navigating the Tables of a DataSet
- •Updating DataSets
- •The DataForm Wizard
- •Handling Identity Fields
- •Transactions
- •Performing Update Operations
- •Updating Tables Manually
- •Building and Using Custom DataSets
- •Summary
- •An HTML Primer
- •HTML Code Elements
- •Server-Client Interaction
- •The Structure of HTML Documents
- •URLs and Hyperlinks
- •The Basic HTML Tags
- •Inserting Graphics
- •Tables
- •Forms and Controls
- •Processing Requests on the Server
- •Building a Web Application
- •Interacting with a Web Application
- •Maintaining State
- •The Web Controls
- •The ASP.NET Objects
- •The Page Object
- •The Response Object
- •The Request Object
- •The Server Object
- •Using Cookies
- •Handling Multiple Forms in Web Applications
- •Summary
- •The Data-Bound Web Controls
- •Simple Data Binding
- •Binding to DataSets
- •Is It a Grid, or a Table?
- •Getting Orders on the Web
- •The Forms of the ProductSearch Application
- •Paging Large DataSets
- •Customizing the Appearance of the DataGrid Control
- •Programming the Select Button
- •Summary
- •How to Serve the Web
- •Building a Web Service
- •Consuming the Web Service
- •Maintaining State in Web Services
- •A Data-Driven Web Service
- •Consuming the Products Web Service in VB
- •Summary
796 Chapter 17 ERROR HANDLING AND DEBUGGING
highlight a row in a grid that doesn’t exist). In this case, fixing the logic error would automatically fix the runtime error.
Exceptions and Structured Exception Handling
A runtime error in VB.NET generates an exception. An exception is a response to the error condition that the program just generated. Figure 17.6 is an example of an exception message. This is the dialog that appears when you are running your program in the IDE. If the same error were to be encountered by a user running your program, the dialog would look slightly different, as seen in Figure 17.7.
Figure 17.6
Design-time error message
Figure 17.7
Runtime error message
Note that this dialog gives the user the opportunity to continue the program. In some rare cases, this might be desirable, but in most cases you probably would not want your users attempting to continue after a program exception has occurred. Think about it—your program has just encountered some form of data that it cannot handle correctly, and now it’s asking the user if it should attempt to ignore that bad data and continue. It is difficult to predict what type of further problems might result as the program continues on and attempts to handle the bad data. Most likely, further exceptions will be generated as the subsequent lines of code attempt to deal with the same unexpected data.
If we don’t want our users handling an exception that the program generates, then we’ll simply have to handle it ourselves. The Visual Basic .NET error-handling model allows us to do just that. An error handler is a section of VB.NET code that allows you to detect exceptions and perform the necessary steps to recover from them. What follows are some exception-handling code examples.
Copyright ©2002 SYBEX, Inc., Alameda, CA |
www.sybex.com |
EXCEPTIONS AND STRUCTURED EXCEPTION HANDLING 797
Studying an Exception
The exception dialogs shown in Figures 17.6 and 17.7 were generated by the VB.NET code shown in Listing 17.1.
Listing 17.1: An Unhandled Exception
Private Sub Button2_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button2.Click Dim s As String
s = “answer”
Button2.Text = s.Substring(10, 1) End Sub
This code is attempting to display the eleventh character in the string “answer”. Seeing as the word “answer” contains only six characters, you can imagine how an exception might be generated. Let’s examine at the exact phrasing of the exception to learn as much as possible about this particular error.
An unhandled exception of type ‘System.ArgumentOutOfRangeException’ occurred in mscorlib.dll
Additional information: Index and length must refer to a location within the string.
Note This seems almost too trivial to mention, but always thoroughly read the exceptions that your program generates. Their purpose is to give you a brief description of the condition that caused the error, which of course is necessary to know before you can figure out how to handle it.
The first thing to notice is the fact that this message refers to this runtime error as an unhandled exception. This means that the line of code that generated this error is not contained within an exception-handling block.
The second interesting piece of information is that this exception is of type System.ArgumentOutOfRangeException, whatever that means. What’s important to note is that the different types of errors can be classified in groups. This is important when we you realize that the .NET Framework exception-handling mechanism follows the same object-oriented design principles that the rest of the Framework follows. An exception creates an instance of an object, and that object is a descendent of class Exception.
The error message above is telling us that the exception object instance generated is of class (type) System.ArgumentOutOfRangeException, which is a descendent of class Exception.
The “additional information” block gives us some specific notes on the nature of the error. It tells us that the index and length parameters of the Substring method must both lie within the boundaries of the string. In our case, we attempted to retrieve the eleventh character of a six-character string, clearly outside the boundary.
Copyright ©2002 SYBEX, Inc., Alameda, CA |
www.sybex.com |
798 Chapter 17 ERROR HANDLING AND DEBUGGING
Getting a Handle on this Exception
Listing 17.2 is the same defective code statement as Listing 17.1, but with a simple exception handler wrapped around it.
Listing 17.2: Handling an Exception, Version 1
Private Sub Button2_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button2.Click Dim s As String
s = “answer” Try
Button2.Text = s.Substring(10, 1) Catch
Button2.Text = “error” End Try
End Sub
This code attempts to do the same thing as the code above, but this time the faulty Substring statement is wrapped around a Try…Catch…End Try block. This block is a basic exception handler. If any of the code after the Try statement generates an exception, then program control automatically jumps to the code after the Catch statement. If no exceptions are generated in the code under the Try statement, then the Catch block is skipped. When this code is run, the System.ArgumentOutOfRangeException is generated, but now the code does not terminate with a message box. Instead, the text property of Button2 is set to the word “error”, and the program continues along.
Listing 17.3 handles the same error in a slightly different way.
Listing 17.3: Handling an Exception, Version 2
Private Sub Button2_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button2.Click Dim s As String
s = “answer” Try
Button2.Text = s.Substring(10, 1) Catch oEX As Exception
Call MsgBox(oEX.Message) End Try
End Sub
In this example, the exception generates an instance of the Exception class and places that instance in a variable named oEX. Having the exception instance variable is useful because it can give you the text of the exception, which we display in a message box here. Of course, displaying the exception message in a message box is pretty much the same thing that your program does when an unhandled
Copyright ©2002 SYBEX, Inc., Alameda, CA |
www.sybex.com |
EXCEPTIONS AND STRUCTURED EXCEPTION HANDLING 799
exception is generated, so it’s doubtful that you would do this in your own program. However, you could log the exception text to the event log or a custom error file.
Note that the exception handlers above do not differentiate between types of errors. If any exception is generated within the Try block, then the Catch block is executed. You can also write exception handlers that handle different classes of errors, as seen in Listing 17.4.
Listing 17.4: Handling an Exception, Version 3
Private Sub Button3_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button3.Click
Try
Button3.Text = lbStates.SelectedItem.ToString
Catch oEX As System.NullReferenceException
Call MsgBox(“Please select an item first”)
Catch oEX As Exception
Call MsgBox(“Some other error: “ & oEX.Message)
End Try
End Sub
This code attempts to take the selected item in a ListBox named lbStates and display it as the caption of a button. If no item is selected in the ListBox, then a System.NullReferenceException will be generated, and we use that information to tell the user to select an item in the ListBox. If any other type of exception is generated, then this code displays the text of that error message.
Note that, in the list of exceptions in Listing 17.4, the more specific exception handler comes first and the more general exception handler comes last. This is how you’ll want to code all of your multiple Catch exception handlers so that they are handled in the correct order. If you put your more general Catch handlers first, then they will execute first and override the more specific handlers.
Also note that the variable oEX is reused in each of the exception blocks. This is possible because the Catch statement actually serves as a declaration of that variable (note that I didn’t have to Dim the oEX variable anywhere) and that the oEX variable has a local scope only within the Catch block.
Note that because the Exception instance is declared in each Catch block, it has scope only within that block. The code in Listing 17.5 is illegal for scoping reasons.
Listing 17.5: Handling an Exception, Version 4 (Illegal)
Private Sub Button3_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button3.Click
Try
Button3.Text = lbStates.SelectedItem.ToString
Catch oEX As System.NullReferenceException
Call MsgBox(“please select an item first”)
Catch oEX As Exception
Call MsgBox(“some other error”)
End Try
MsgBox(oEX.message)
End Sub
Copyright ©2002 SYBEX, Inc., Alameda, CA |
www.sybex.com |