How to trace and debug in Visual C++ .NET and in Visual C++ 2005 (815787)



The information in this article applies to:

  • Microsoft Visual C++ 2005 Express Edition
  • Microsoft Visual C++ .NET (2003)
  • Microsoft Visual C++ .NET (2002)
  • Microsoft .NET Framework 1.1
  • Microsoft .NET Framework 1.0

For a Microsoft Visual Basic .NET version of this article, see 313417.
For a Microsoft Visual C# .NET version of this article, see 815788.

This article refers to the following Microsoft .NET Framework Class Library namespace:
  • System::Diagnostics

IN THIS TASK

SUMMARY

This article describes how to use the Debug class and the Trace class. These classes are available in the Microsoft .NET Framework. You can use these classes to provide information about the performance of an application during application development, or after deployment to production. These classes are only one part of the instrumentation features that are available in the .NET Framework.

Back to the top

Requirements

The following list outlines the recommended hardware, software, network infrastructure, and service packs that you need:
  • Microsoft Windows 2000, Microsoft Windows XP, or Microsoft Windows Server 2003
  • Microsoft Visual C++ .NET or Microsoft Visual C++ 2005
This article also assumes that you are familiar with application debugging.

Back to the top

Description of the technique using the Debug class

The steps in the "Create a Sample That Uses the Debug Class" section of this article demonstrate how to create a console application that uses the Debug class to provide information about an application during run time.

While an application runs, you can use methods of the Debug class to display messages that help you to track the application during run time, to detect errors, or to provide performance measurement information. By default, the messages that the Debug class displays appear in the Output window in Visual Studio .NET.

The sample code in this article uses the WriteLine method to display a message, followed by a line terminator. When you use this method to display a message, each message appears on a separate line in the Output window.

When you use the Assert method of the Debug class, the Output window displays a message only if a specified condition evaluates to false. The message also appears to the user in a modal dialog box. This dialog box includes the message, the project name, and the Debug::Assert statement number. The dialog box also includes the following three buttons:
  • Abort: The application stops running.
  • Retry: The application enters debug mode.
  • Ignore: The application proceeds.
You must click one of these buttons before the application can continue.

You can also direct output from the Debug class to destinations other than the Output window. The Debug class contains a collection that is named Listeners that includes Listener objects.

Each Listener object in the Listeners collection receives output from the Debug class, and then directs this output to a specified target.

Use the TextWriterTraceListener class to define Listener objects. You can specify the target for a TextWriterTraceListener class by using an appropriate constructor.

Some possible output targets include the following:
  • The Console window by using the System::Console::Out property.
  • A text (.txt) file by using the System::IO::File::CreateText("FileName.txt") statement.
After you create a TextWriterTraceListener object, you must add the object to the Debug::Listeners collection to receive output from a Debug class.

Back to the top

Create a sample that uses the Debug class

  1. Start Microsoft Visual Studio .NET or Microsoft Visual Studio 2005.
  2. On the File menu, point to New, and then click Project.
  3. In Visual C++ .NET 2002, click Visual C++ Projects under Project Types, and then click Managed C++ Application under Templates.

    In Visual C++ .NET 2003, click Visual C++ Projects under Project Types, and then click Console Application (.NET) under Templates.

    Note In Visual Studio 2005, click Visual C++ under Project Types.
  4. In the Name text box, type ConInfo, and then click OK.
  5. In Solution Explorer, double-click ConInfo.cpp to display the code window.
  6. In the ConInfo.cpp file, add the following statements before the _tmain method:
    #using <System.Xml.Dll>
    using namespace System::Diagnostics;
    If you are using Visual C++ .NET 2002, add the following additional code in the code window before the using directives:
    #using <System.Dll>	
    #include <tchar.h>
  7. To initialize variables to contain information about a product, add the following declaration statements to the _tmain method:
    String * sProdName = S"Widget";
    int iUnitQty = 100;
    double  dUnitCost = 1.03;
  8. You can use different methods of the Debug class to display messages that track the running of an application as follows:
    • Specify the message to display as the first input parameter of the WriteLine method of the Debug class.
      Debug::WriteLine(S"Debug Information-Product Starting ");
    • For readability, use the Indent method of the Debug class to indent subsequent messages in the Output window as follows:
      Debug::Indent();
    • To display the content of selected variables, use the WriteLine method of the Debug class as follows:
      Debug::WriteLine(String::Concat(S"The product name is ", sProdName));
      Debug::WriteLine(String::Concat(S"The available units on hand are ", iUnitQty.ToString()));
      Debug::WriteLine(String::Concat(S"The per unit cost is ", dUnitCost.ToString()));
      Note The Concat method of the String class concatenates two strings.
    • You can also use the WriteLine method of the Debug class to display the namespace and the class name for an object. For example, the following code displays the System::Xml::XmlDocument namespace in the Output window:
      System::Xml::XmlDocument * oxml = new System::Xml::XmlDocument();
      Debug::WriteLine(oxml);
    • To format the output, you can include a category as an optional, second input parameter of the WriteLine method of the Debug class. If you specify a category, the format of the Output window message is as follows:category: message For example, the first line of the following code displays the followingField: The product name is Widget in the Output window:
      Debug::WriteLine(String::Concat(S"The product name is " , sProdName), S"Field");
      Debug::WriteLine(String::Concat(S"The units on hand are ",iUnitQty.ToString()) ,S"Field");
      Debug::WriteLine(String::Concat(S"The per unit cost is ", dUnitCost.ToString()) ,S"Field");
      Debug::WriteLine(String::Concat(S"Total Cost is  ", (iUnitQty * dUnitCost).ToString()),S"Calc");
    • When you use the WriteLineIf method of the Debug class, the Output window displays messages only if a designated condition evaluates to true. The first input parameter of the WriteLineIf method is the condition that is evaluated. The second parameter of the WriteLineIf method is the message that appears only if the condition in the first parameter evaluates to true.
      Debug::WriteLineIf(iUnitQty > 50, S"This message WILL appear");
      Debug::WriteLineIf(iUnitQty < 50, S"This message will NOT appear");
    • Use the Assert method of the Debug class so that the Output window displays a message only if a specified condition evaluates to false.
      Debug::Assert(dUnitCost > 1, S"Message will NOT appear");
      Debug::Assert(dUnitCost < 1, S"Message will appear since dUnitcost  < 1 is false");
    • Create TextWriterTraceListener objects for the Console window (tr1) and for a text file that is named Output.txt (tr2), and then add both objects to the Debug::Listeners collection.
      TextWriterTraceListener * tr1 = new TextWriterTraceListener(System::Console::Out);
      Debug::Listeners->Add(tr1);
      
      TextWriterTraceListener * tr2 = new TextWriterTraceListener(System::IO::File::CreateText(S"Output.txt"));
      Debug::Listeners->Add(tr2);
    • For readability, use the Unindent method of the Debug class to remove the indentation for subsequent messages that the Debug class generates. When you use the Indent method and the Unindent method together, a reader can distinguish the output as a group.
      Debug::Unindent();
      Debug::WriteLine(S"Debug Information-Product Ending");
    • To make sure that each Listener object receives all its output, call the Flush method for the Debug class buffers.
      Debug::Flush();
    Add the appropriate methods to your code, and then press CTRL+SHIFT+B to build the application.
Back to the top

Use the Trace class

You can also use the Trace class to display messages that track the running of an application. The Trace class and the Debug class contain similar methods to display output. These methods include the following:
  • WriteLine
  • WriteLineIf
  • Indent
  • Unindent
  • Assert
  • Flush
You can use the Trace class and the Debug class separately or together in the same application. In a Debug Solution Configuration project, both Trace output and Debug output are active. The project generates output from both these classes to all Listener objects. However, a Release Solution Configuration project only generates output from a Trace class. The Release Solution Configuration project ignores any Debug class method calls.
Trace::WriteLine(String::Concat(S"The product name is ",sProdName));
Trace::WriteLine(String::Concat(S"The product name is ",sProdName), S"Field" );
Trace::WriteLineIf(iUnitQty > 50, S"This message WILL appear");
Trace::Assert(dUnitCost > 1, S"Message will NOT appear");

Trace::Unindent();
Trace::WriteLine(S"Trace Information-Product Ending");

Trace::Flush();

Console::ReadLine();
Back to the top

Complete code listing

#include "stdafx.h"

#using <mscorlib.dll>
//Uncomment following line for Microsoft Visual C++ .NET 2002
//#using <System.Dll>
#using <System.Xml.Dll>
//Uncomment following line for Microsoft Visual C++ .NET 2002
//#include <tchar.h>

using namespace System;
using namespace System::Diagnostics;

// This is the entry point for this application
int _tmain(void)
{
    String * sProdName = S"Widget";
    int iUnitQty = 100;
    double  dUnitCost = 1.03;
    Debug::WriteLine(S"Debug Information-Product Starting ");
    Debug::Indent();
    Debug::WriteLine(String::Concat(S"The product name is ", sProdName));
    Debug::WriteLine(String::Concat(S"The available units on hand are ", iUnitQty.ToString()));
    Debug::WriteLine(String::Concat(S"The per unit cost is ", dUnitCost.ToString()));

    System::Xml::XmlDocument * oxml = new System::Xml::XmlDocument();
    Debug::WriteLine(oxml);

    Debug::WriteLine(String::Concat(S"The product name is " , sProdName), S"Field");
    Debug::WriteLine(String::Concat(S"The units on hand are ",iUnitQty.ToString()) ,S"Field");
    Debug::WriteLine(String::Concat(S"The per unit cost is ", dUnitCost.ToString()) ,S"Field");
    Debug::WriteLine(String::Concat(S"Total Cost is  ", (iUnitQty * dUnitCost).ToString()),S"Calc");

    Debug::WriteLineIf(iUnitQty > 50, S"This message WILL appear");
    Debug::WriteLineIf(iUnitQty < 50, S"This message will NOT appear");

    Debug::Assert(dUnitCost > 1, S"Message will NOT appear");
    Debug::Assert(dUnitCost < 1, S"Message will appear since dUnitcost  < 1 is false");

    TextWriterTraceListener * tr1 = new TextWriterTraceListener(System::Console::Out);
    Debug::Listeners->Add(tr1);

    TextWriterTraceListener * tr2 = new TextWriterTraceListener(System::IO::File::CreateText(S"Output.txt"));
    Debug::Listeners->Add(tr2);


    Debug::WriteLine(String::Concat(S"The product name is ",sProdName));
    Debug::WriteLine(String::Concat(S"The available units on hand are ",iUnitQty.ToString()));
    Debug::WriteLine(String::Concat(S"The per unit cost is ", dUnitCost.ToString()));
    Debug::Unindent();
    Debug::WriteLine(S"Debug Information-Product Ending");
    Debug::Flush();

    Trace::WriteLine(S"Trace Information-Product Starting ");
    Trace::Indent();

    Trace::WriteLine(String::Concat(S"The product name is ",sProdName));
    Trace::WriteLine(String::Concat(S"The product name is ",sProdName), S"Field" );
    Trace::WriteLineIf(iUnitQty > 50, S"This message WILL appear");
    Trace::Assert(dUnitCost > 1, S"Message will NOT appear");

    Trace::Unindent();
    Trace::WriteLine(S"Trace Information-Product Ending");

    Trace::Flush();

    Console::ReadLine();

    return 0;
}
Note You must add the common language runtime support compiler option (/clr:oldSyntax) in Visual C++ 2005 to successfully compile the previous code sample. To add the common language runtime support compiler option in Visual C++ 2005, follow these steps:
  1. Click Project, and then click <ProjectName> Properties.

    Note <ProjectName> is a placeholder for the name of the project.
  2. Expand Configuration Properties, and then click General.
  3. Click to select Common Language Runtime Support, Old Syntax (/clr:oldSyntax) in the Common Language Runtime support project setting in the right pane, click Apply, and then click OK.
For more information about the common language runtime support compiler option, visit the following Microsoft Web site:

/clr (Common Language Runtime Compilation)
http://msdn2.microsoft.com/en-us/library/k8d11d4s.aspx

Back to the top

Verify that your application works

  1. Make sure that your project uses the Debug Solution Configuration. To do this, follow these steps:
    1. On the Build menu, click Configuration Manager.
    2. Click Debug in the Active Solution Configuration list, and then click Close.
  2. Press CTRL+ALT+O to display the Output window.
  3. Press F5 to start the application in debug mode.
  4. When the Assertion Failed dialog box appears, click Ignore.
  5. In the Console window, press ENTER. The application exits, and the Output window displays the following output:
    Debug Information-Product Starting 
        The product name is Widget
        The available units on hand are 100
        The per unit cost is 1.03
        System.Xml.XmlDocument
        Field: The product name is Widget
        Field: The units on hand are 100
        Field: The per unit cost is 1.03
        Calc: Total Cost is  103
        This message WILL appear
        ---- DEBUG ASSERTION FAILED ----
    ---- Assert Short Message ----
    Message will appear since dUnitcost  < 1 is false
    ---- Assert Long Message ----
    
        The product name is Widget
        The available units on hand are 100
        The per unit cost is 1.03
    Debug Information-Product Ending
    Trace Information-Product Starting 
        The product name is Widget
        Field: The product name is Widget
        This message WILL appear
    Trace Information-Product Ending
    Additionally, the Output.txt file should contain the following output:
        The product name is Widget
        The available units on hand are 100
        The per unit cost is 1.03
    Debug Information-Product Ending
    Trace Information-Product Starting 
        The product name is Widget
        Field: The product name is Widget
        This message WILL appear
    Trace Information-Product Ending

    Note You notice this output when you use the code that is provided in the "Complete Code Listing" section of this article. The Output.txt file is located in the same directory as the project source files. By default, the project source files are stored in the C:\Documents and Settings\UserName\My Documents\Visual Studio Projects\ConInfo\ directory.
Back to the top

Troubleshooting

  • If the solution configuration type is set to Release, the Debug class output is ignored.
  • After you create a TextWriterTraceListener object for a particular target, the TextWriterTraceListener object receives output from the Trace class and from the Debug class. This behavior occurs regardless of whether you use the Add method of the Trace class or the Add method of the Debug class to add the TextWriterTraceListener object to the Listeners collection.
  • If you add a Listener object for the same target in the Trace class and in the Debug class, each line of output appears two times, regardless of whether the Debug class or the Trace class generates the output.
    TextWriterTraceListener * mywriter = new TextWriterTraceListener(System::Console::Out);
    Debug::Listeners->Add(mywriter);
    
    TextWriterTraceListener * myCreator = new TextWriterTraceListener(System::Console::Out);
    Debug::Listeners->Add(myCreator);
Back to the top

REFERENCES

For more information about the Trace class, visit the following Microsoft Developer Network (MSDN) Web site:For more information about the Debug class, visit the following MSDN Web site:

For more information about tracing, see the following topic in the Microsoft GotDotNet QuickStart tutorials:Back to the top

Modification Type:MajorLast Reviewed:1/18/2006
Keywords:kbProgramming kbDebug kbConsole kbXML kbWinDBG kbHOWTOmaster KB815787 kbAudDeveloper