Tracing

Team-Fly    

Developing XML Web Services and Server Components with Visual C#™ .NET and the .NET Framework, Exam Cram™ 2 (Exam 70-320)
By Amit Kalani, Priti Kalani

Table of Contents
Chapter 10.  Testing and Debugging


Tracing is a process for collecting information about program execution. Information revealed through tracing can help you resolve errors and issues with an application.

Using the Trace and Debug Classes

Tracing in Visual C# .NET can also be done by generating messages about a program's execution with the use of the Debug and Trace classes. The Debug and Trace classes both belong to the System.Diagnostics namespace and have members with the same names.

Table 10.1 summarizes the important members of both the Debug and Trace classes.

Table 10.1. Important Members of the Debug and Trace Classes

Member

Type

Description

Assert()

Method

Checks for a condition and displays a message if the condition is false

AutoFlush

Property

Specifies whether the Flush() method should be called on the listeners after every write

Close()

Method

Flushes the output buffer and then closes the listeners

Fail()

Method

Displays an error message

Flush()

Method

Flushes the output buffer and causes the buffered data to be written to the listeners

Listeners

Property

Specifies the collection of listeners that is monitoring the output generated by the Trace and Debug classes

Write()

Method

Writes the given information to the trace listeners in the Listeners collection

WriteIf()

Method

Writes the given information to the trace listeners in the Listeners collection only if a condition is true

WriteLine()

Method

Acts the same as the Write() method, but appends the information with a newline character

WriteLineIf()

Method

Acts the same as the WriteIf() method, but appends the information with a newline character

The members of the Debug class are conditionally compiled only when the DEBUG symbol is defined. On the other hand, members of the Trace class are conditionally compiled only when the TRACE symbol is defined.

Visual Studio .NET provides two compilation configurations already set up for you: the Debug configuration and the Release configuration. The Debug configuration defines the DEBUG and TRACE symbols, whereas the Release configuration defines only the TRACE symbol. You can define additional symbols and compilation configurations using the project's Property Pages dialog box in Visual Studio .NET.

For example, the following code segment displays the message only when the TRACE symbol is defined and when the expression intFac < 1 evaluates to true:

 Trace.WriteLineIf(intFac < 1, "There was an overflow"); 

Trace Listeners

Listeners are the classes responsible for forwarding, recording, and displaying the messages generated by the Trace and Debug classes. You can have multiple listeners associated with Trace and Debug classes by adding Listener objects to their Listeners properties.

graphics/alert_icon.gif

Both the Debug and Trace classes share their Listeners collections, so an object added to the Listeners collection of the Debug class is automatically available in the Trace class, and vice versa.


The TraceListener class is an abstract class that belongs to the System.Diagnostics namespace and has three implementations:

  • DefaultTraceListener class An object of this class is automatically added to the Listeners collection. Its behavior is to write messages on the Output window.

  • TextWriterTraceListener class An object of this class writes messages to any class that derives from the Stream or TextWriter class that includes the console or a file.

  • EventLogTraceListener class An object of this class writes messages to the Windows event log.

You can also create a custom listener by inheriting from the TraceListener class. When doing so, you must at least implement the Write() and WriteLine() methods.

Trace Switches

Trace switches are used to control the level of tracing that needs to be done on a program. They can be set via machine (machine.config) or application (web.config) configuration files that are based on the Extensible Markup Language (XML). The application automatically picks up the changes from the configuration file when it restarts, which is especially useful when the application you are working with is in production mode.

Two predefined classes for creating trace switches are available the BooleanSwitch class and the TraceSwitch class. Both of these classes derive from the abstract Switch class. You can also define your own trace switch classes by deriving classes from the Switch class.

You use the BooleanSwitch class to differentiate between two modes of tracing: trace-on and trace-off. Its default value is 0, which corresponds to the trace-off state. If it is set to any nonzero value, it corresponds to the trace-on state.

Unlike BooleanSwitch, the TraceSwitch class provides five levels of tracing switches. These levels are defined by the TraceLevel enumeration and are listed in Table 13.4. The default value of TraceLevel for a TraceSwitch object is 0 (off).

Table 10.2. The TraceLevel Enumeration

Enumerated Value

Integer Value

Type of Tracing

Off

0

None

Error

1

Only error messages

Warning

2

Warning messages and error messages

Info

3

Informational messages, warning messages, and error messages

Verbose

4

Verbose messages, informational messages, warning messages, and error messages

graphics/alert_icon.gif

For a BooleanSwitch object, if any nonzero (negative or positive) value is specified in the configuration file, the BooleanSwitch object's Enabled property is set to true. For a TraceSwitch object, if a value greater than 4 is specified, the Level property of the object is set to TraceLevel.Verbose (4). If a negative value is specified, a StackOverflowException exception occurs at runtime.


Take the following steps to learn how to use trace switches in an application:

  1. Create a blank solution using Visual Studio .NET. Name the solution C10 and specify its location as C:\EC70320. Add a new Visual C# Windows application project (Example10_1) to the solution.

  2. Add a TextBox control (txtNumber), a Button control (btnCalculate), and a Label control (lblResult) to the form. Switch to Code view and add the following using directive:

     using System.Diagnostics; 
  3. Add the following code in the class definition:

     static TraceSwitch traceSwitch = new TraceSwitch("FactorialTrace",           "Trace the factorial application"); 
  4. Add the following code to the Click event handler of the Calculate button:

     private void btnCalculate_Click(object sender, System.EventArgs e) {     if (traceSwitch.TraceVerbose)        Debug.WriteLine("Inside Button Click event handler");     Debug.Indent();     int intNumber = Convert.ToInt32(txtNumber.Text);     if (traceSwitch.TraceError)         Debug.Assert(intNumber >= 0, "Invalid value",            "negative value in debug mode");     int intFac = 1;     for (int i = 2; i <= intNumber; i++)     {         intFac = intFac * i;         if (traceSwitch.TraceInfo)            Debug.WriteLine(i, "Factorial Program Debug, Value of i");     }     if (traceSwitch.TraceWarning)         Debug.WriteLineIf(intFac < 1, "There was an overflow",              "Factorial Program Debug");     lblResult.Text = String.Format(            "The factorial of {0} is {1}", intNumber, intFac);     Debug.Unindent();     if (traceSwitch.TraceVerbose)         Debug.WriteLine("Done with computations."); } 
  5. Add a new application configuration file (App.config) to the project. Modify its <configuration> element as shown here:

     <configuration>     <system.diagnostics>         <switches>             <add name="FactorialTrace" value="4" />         </switches>     </system.diagnostics> </configuration> 
  6. Run the project using the Debug configuration. Enter a value of 5; note that all messages appear in the Output window. Now, try again with a negative value; you'll see an Assertion Failed dialog box. Next, enter a large value; you see all the errors as well as all the warning messages. Close the form and then modify the XML file by changing the value of FactorialTrace to 3. You should now see all the messages except the one in the if statement that checks for TraceLevel.Verbose. Repeat the process with the values of FactorialTrace in the configuration file changed to 2, 1, and 0.

  7. Modify the program to change all Debug statements to the Trace statements; then run the project using the Release configuration. Change the FactorialTrace switch value to 4 and then repeat the process discussed in step 6. You see all the error and warning messages.

graphics/alert_icon.gif

To enable trace switches in a Web application or a Web service, you need to add the <system.diagnostics> element to the Web application configuration file (web.config).


Conditional Compilation

The C# programming language provides a set of preprocessing directives (as listed in Table 10.3). You can use these directives to skip sections of source files for compilation, report errors and warnings, or mark distinct regions of source code.

Table 10.3. C# Preprocessing Directives

Directives

Description

#if, #else, #elif, and #endif

These directives conditionally skip sections of code. The skipped sections are not part of the compiled code.

#define and #undef

These directives define or undefine symbols in the code.

#warning and #error

These directives explicitly generate error or warning messages.

#line

This directive alters the line numbers and source filenames reported by the compiler in warning and error messages.

#region and #endregion

These directives mark sections of code. Visual Studio .NET uses these directives to show, hide, and format code.

The following example shows how to define a symbol named MYSYMBOL in your program:

 #define MYSYMBOL 

The following example shows how to use a preprocessor directive to include or exclude code from compilation:

 #if MYSYMBOL     // call ThisMethod() only when MYSYMBOL is defined     ThisMethod(); #else     // call ThisMethod() only when MYSYMBOL is NOT defined     InitializeReleaseMode(); #endif 

Another option for conditional compilation is the Conditional attribute, which can be used to mark a method for conditional compilation. The Conditional attribute takes one argument that specifies a symbol. If the symbol definition is available, the code of the method is included; otherwise, the code of the method is excluded from the compiled code. For example, the call to the following method executes only if the DEBUG symbol is defined:

 [Conditional("DEBUG")] public void DebugMethod() {     // Method code goes here } 

graphics/alert_icon.gif

A method must have its return type set to void to have the Conditional attribute applied to it.



    Team-Fly    
    Top


    MCAD Developing XML Web Services and Server Components with Visual C#. NET and the. NET Framework Exam Cram 2 (Exam Cram 70-320)
    Managing Globally with Information Technology
    ISBN: 789728974
    EAN: 2147483647
    Year: 2002
    Pages: 179

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net