An About Visual Basic reader wrote to ask, "There are two VB6 methods, Line and Circle, that don't seem to work. I'm using Form Load and I have tried changing all of the properties, but the line doesn't show. When I look at it using VB6 Debug, it seems that the statements have been executed. Why not?"
The answer turned out to be that when you execute these commands in the Form Load event in VB6, the Form doesn't really exist yet. (It's mid way through the process of being created.) So the commands execute, but when the Form is finally displayed, these objects aren't in it.
In VB6, it was necessary to insert debugging statements into the code temporarily to see this. In other words, add debugging code for the events that VB6 provides for forms (Activate, Paint, GotFocus, Resize, Initialize, and finally Load).
Private Sub Form_Activate() Debug.Print "Activate" End Sub
You can easily see then that the sequence of these events in VB6 is:
Initialize Load Resize Activate GotFocus Paint
This is called "tracing" the execution and it's one of the most valuable debugging techniques available. But VB.NET gives you much better ways to do it. (The old VB6 Debug object is gone, but there's much more that you can do with the VB.NET System.Diagnostics.Debug class.)
TRACE and DEBUG Conditional Compilation Constants in VB.NET
The main debugging tools are in the Debug toolbar in VB.NET. (All my examples are from VB.NET 2008.) You're probably already familiar with breakpoints, stepping through code, have seen lots of WriteLine statements. So I'm going to cover some things that you might not have seen.
VB.NET provides two Conditional Compilation Constants, named DEBUG and TRACE that can control whether or not the VB.NET compiler even creates code. If DEBUG is "not defined" then the MsgBox statement below isn't even part of the compiled program:
#If DEBUG Then MsgBox("DEBUG Compiler Constant defined") #End If
If you look up ConditionalAttribute Class at Microsoft, it tells you that there are three ways to define these:
- Compiler command-line options (for example, /define:DEBUG).
- Environment variables in the operating system shell (for example, set DEBUG=1).
- Pragmas in the source code (for example, #define DEBUG to define the compilation variable and #undef DEBUG to undefine it).
If you saw a Microsoft engineer reading a book and you asked, "What are you reading?" The engineer would probably answer, "A book." The documentation above is correct, but in the real world, virtually everyone "defines" these constants in the Properties dialog for a VB.NET project. (Which, in turn, uses the techniques above.)
To define these constants, right-click the project, select Properties, select the Compile tab, click the Advanced Compile Options... button at the bottom and a window will open with checkboxes to define these constants.
Just to be complete, Visual Studio gives you another way to do this - the Configuration Manager dialog. But it's even harder to find because you have to select Tools > Options > Projects and Solutions > General and then check the option "Show advanced build configurations" before you can even display the Configuration Manager. Then you can select a Debug configuration. (Don't confuse this with the DEBUG Conditional Compilation constant or the Debug object. These are three different things.)
According to Microsoft (I added the bolding to highlight the one difference):
"By default, the Debug configuration for a project defines DEBUG. When DEBUG is defined, Debug class methods generate output to the Output window. When it is not defined, Debug class methods are not compiled and no Debug output is generated."
"By default, all configurations for a project define TRACE. When TRACE is defined, Trace class methods generate output to the Output window. When it is not defined, Trace class methods are not compiled and no Trace output is generated."
Remember, the Project Properties will override these configurations.
But there's still one more hidden difference between what Microsoft's documentation says and what actually happens. Try this code:
Console.WriteLine("Both DEBUG and TRACE checked" & _ " - Debug Configuration") #If DEBUG Then Debug.WriteLine("DEBUG Compiler Constant defined" & _ " - Debug object used.") Trace.WriteLine("DEBUG Compiler Constant defined" & _ " - Trace object used.") #End If #If TRACE Then Debug.WriteLine("Trace Compiler Constant defined" & _ " - Debug object used.") Trace.WriteLine("Trace Compiler Constant defined" & _ " - Trace object used.") #End If
According to Microsoft's documentation, you should get five messages written to the Output window. But Nooooo ... You get four to the Immediate window and just one (the Console.WriteLine message) in the Output window. That's because there is another default option. And this one isn't even available in the VB.NET 2008 Express edition. (Or, at least, I couldn't find it.) You have to have the full Visual Studio system to even see it.
If you do have Visual Studio (not just the Express edition), go to Tools > Options then click the "Show all settings" checkbox at the bottom. (More options suddenly appear.) Then select Debugging > General and look for "Redirect all Output window text to the Immediate window". Uncheck that and you'll get five messages in the Output window. (Interestingly, not "all" Output window text is redirected. The Console.WriteLine statement goes to the Output window anyway.)
If you read a lot of Microsoft documentation like I do, you will see them claim quite frequently that things are written to the Output window when they're not. It seems to me that the documentation must be written from specifications when the products are still beta and nobody ever actually checks this stuff out.