玄铁剑

成功的途径:抄,创造,研究,发明...
posts - 128, comments - 42, trackbacks - 0, articles - 174

在 Visual C# .NET 中跟踪和调试

Posted on 2007-01-04 21:30 玄铁剑 阅读(344) 评论(0)  编辑 收藏 引用 所属分类: Debug

概要

本文介绍如何使用 DebugTrace 类。Microsoft .NET Framework 中提供了这两个类。在应用程序开发期间或部署到产品后,可以使用这两个类提供有关应用程序性能的信息。这两个类只是 .NET Framework 中所提供配置功能的一部分。

要求

下面的列表概括了推荐的硬件、软件、网络结构以及所需的 Service Pack:
Microsoft Windows 2000 或 Microsoft Windows XP
Microsoft Visual C# .NET
本文还假定您熟悉程序调试。

方法说明


使用 Debug 类创建一个示例一节中介绍的步骤演示了如何创建使用 Debug 类以提供有关程序执行信息的控制台应用程序。

当程序运行时,您可以使用 Debug 类的方法来生成消息,以帮助您监视程序执行顺序、检测故障或提供性能度量信息。默认情况下,Debug 类产生的消息显示在 Visual Studio 集成开发环境 (IDE) 的“输出”窗口中。

该代码示例使用 WriteLine 方法生成后面带有行结束符的消息。当您使用此方法生成消息时,每条消息在“输出”窗口中均显示为单独的一行。

如果使用 Debug 类的 Assert 方法,那么只有在指定条件计算为 false 时,“输出”窗口才显示消息。该消息还在一个模式对话框中向用户显示。该对话框包括消息、项目名和 Debug.Assert 语句编号。该对话框还包括下列三个命令按钮:
终止:应用程序停止运行。
重试:应用程序进入调试模式。
忽略:应用程序继续。
用户必须先单击这些按钮中的一个,然后应用程序才可以继续。

您还可以指示从 Debug 类向“输出”窗口以外的目标进行输出。Debug 类有一个名为 Listeners 的集合,该集合包括一些 Listener 对象。

每个 Listener 对象都监视 Debug 输出并使输出指向指定的目标。

Listener 集合中的每个 Listener 都接收 Debug 类生成的任何输出。请使用 TextWriterTraceListener 类定义 Listener 对象。可以通过 TextWriterTraceListener 类的构造函数为该类指定目标。

一些可能的输出目标包括:
使用 System.Console.Out 属性指定“控制台”窗口作为输出目标。
使用 System.IO.File.CreateText("FileName.txt") 语句指定文本文件 (.txt) 作为输出目标。
创建 TextWriterTraceListener 对象后,必须将该对象添加到 Debug.Listeners 集合才可接收调试输出。

使用 Debug 类创建一个示例

1.启动 Visual Studio .NET。
2.新建一个名为 conInfo 的新 Visual C# .NET 控制台应用程序项目。将创建 Class1。
3.在 Class1 的顶部添加以下名称空间。
using System.Diagnostics;
4.要初始化变量以使其包含产品的相关信息,请将下面的声明语句添加到 Main 方法:
string sProdName = "Widget";
int iUnitQty = 100;
double dUnitCost = 1.03;
5.将类生成的消息指定为 WriteLine 方法的第一个输入参数。按 CTRL+ALT+O 组合键以确保“输出”窗口可见。
Debug.WriteLine("Debug Information-Product Starting ");
6.为了清晰易读,请使用 Indent 方法在“输出”窗口中缩进后面的消息:
Debug.Indent();
7.要显示所选变量的内容,请使用 WriteLine 方法,如下所示:
Debug.WriteLine("The product name is " + sProdName);
Debug.WriteLine("The available units on hand are" + iUnitQty.ToString());
Debug.WriteLine("The per unit cost is " + dUnitCost.ToString());
8.您还可以使用 WriteLine 方法显示现有对象的名称空间和类名称。例如,下面的代码在“输出”窗口中显示 System.Xml.XmlDocument 命名空间:
System.Xml.XmlDocument oxml = new System.Xml.XmlDocument();
Debug.WriteLine(oxml);
9.要整理输出,可以包括一个类别作为 WriteLine 方法的第二个可选的输入参数。如果您指定一个类别,则“输出”窗口消息的格式为“类别:消息”。例如,以下代码的第一行在“输出”窗口中显示“Field:The product name is Widget”:
Debug.WriteLine("The product name is " + sProdName,"Field");
Debug.WriteLine("The units on hand are" + iUnitQty,"Field");
Debug.WriteLine("The per unit cost is" + dUnitCost.ToString(),"Field");
Debug.WriteLine("Total Cost is  " + (iUnitQty * dUnitCost),"Calc");
10.仅在使用 Debug 类的 WriteLineIf 方法将指定条件计算为 true 时,“输出”窗口才可以显示消息。将要计算的条件是 WriteLineIf 方法的第一个输入参数。WriteLineIf 的第二个参数是仅在第一个参数的条件计算为真时才显示的消息。
Debug.WriteLineIf(iUnitQty > 50, "This message WILL appear");
Debug.WriteLineIf(iUnitQty < 50, "This message will NOT appear");
11.使用 Debug 类的 Assert 方法,使“输出”窗口仅在指定条件计算为 false 时才显示消息:
Debug.Assert(dUnitCost > 1, "Message will NOT appear");
Debug.Assert(dUnitCost < 1, "Message will appear since dUnitcost < 1 is false");
12.为“控制台”窗口 (tr1) 和名为 Output.txt (tr2) 的文本文件创建 TextWriterTraceListener 对象,然后将每个对象添加到 Debug Listeners 集合中:
TextWriterTraceListener tr1 = new TextWriterTraceListener(System.Console.Out);
Debug.Listeners.Add(tr1);
        
TextWriterTraceListener tr2 = new TextWriterTraceListener(System.IO.File.CreateText("Output.txt"));
Debug.Listeners.Add(tr2);
13.为了清晰易读,请使用 Unindent 方法去除 Debug 类为后续消息生成的缩进。当您将 IndentUnindent 两种方法一起使用时,读取器可以将输出分成组。
Debug.Unindent();
Debug.WriteLine("Debug Information-Product Ending");
14.为了确保每个 Listener 对象收到它的所有输出,请为 Debug 类缓冲区调用 Flush 方法:
Debug.Flush();

使用 Trace 类

您还可以使用 Trace 类生成监视应用程序执行的消息。TraceDebug 类共享大多数相同的方法来生成输出,这些方法包括:
WriteLine
WriteLineIf
Indent
Unindent
Assert
Flush
您可以在同一应用程序中分别或同时使用 TraceDebug 类。在一个“调试解决方案配置”项目中,TraceDebug 两种输出均为活动状态。该项目从这两个类为 Listener 对象生成输出。但是,“发布解决方案配置”项目仅从 Trace 类生成输出。该“发布解决方案配置”项目忽略任何 Debug 类方法调用。
Trace.WriteLine("Trace Information-Product Starting ");
Trace.Indent();

Trace.WriteLine("The product name is "+sProdName);
Trace.WriteLine("The product name is"+sProdName,"Field" );
Trace.WriteLineIf(iUnitQty > 50, "This message WILL appear");
Trace.Assert(dUnitCost > 1, "Message will NOT appear");
        
Trace.Unindent();
Trace.WriteLine("Trace Information-Product Ending");

Trace.Flush();

Console.ReadLine();

确认它可以使用

1.确保 Debug 是当前的解决方案配置。
2.如果“解决方案资源管理器”窗口不可见,请按 CTRL+ALT+L 组合键以显示此窗口。
3.右键单击“conInfo”,然后单击“属性”。
4.在 conInfo 属性页左窗格中,在“配置”文件夹下,请确保箭头指向“调试”。
5.在“配置”文件夹上面的“配置”下拉列表框中,单击“活动(调试)”或“调试”,然后单击“确定”。
6.按 CTRL+ALT+O 以显示“输出”窗口。
7.按 F5 键以运行该代码。在出现“断言失败”对话框时,单击“忽略”。
8.在“控制台”窗口中,按 ENTER 键。此时程序即已完成,“输出”窗口应显示以下输出:
    Debug Information-Product Starting 
    The product name is Widget
    The available units on hand are100
    The per unit cost is 1.03
    System.Xml.XmlDocument
    Field: The product name is Widget
    Field: The units on hand are100
    Field: The per unit cost is1.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 ----


    at Class1.Main(String[] args)  <%Path%>\class1.cs(34)

    The product name is Widget
    The available units on hand are100
    The per unit cost is 1.03
Debug Information-Product Ending
Trace Information-Product Starting 
    The product name is Widget
    Field: The product name isWidget
    This message WILL appear
Trace Information-Product Ending
                    
9.“控制台”窗口和 Output.txt 文件应显示以下输出:
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			
注意:Output.txt 文件与 conInfo 可执行文件 (conInfo.exe) 位于同一目录中。通常情况下,该目录是存储项目源的 \bin 文件夹,默认情况下为 C:\Documents and Settings\User login\My Documents\Visual Studio Projects\conInfo\bin。

完整代码列表

   using System;
   using System.Diagnostics;

   class Class1
   {
      [STAThread]
      static void Main(string[] args)
      {
         string sProdName = "Widget";
         int iUnitQty = 100;
         double  dUnitCost = 1.03;
         Debug.WriteLine("Debug Information-Product Starting ");
         Debug.Indent();
         Debug.WriteLine("The product name is "+sProdName);
         Debug.WriteLine("The available units on hand are"+iUnitQty.ToString());
         Debug.WriteLine("The per unit cost is "+ dUnitCost.ToString());

         System.Xml.XmlDocument oxml = new System.Xml.XmlDocument();
         Debug.WriteLine(oxml);

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

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

         Debug.Assert(dUnitCost > 1, "Message will NOT appear");
         Debug.Assert(dUnitCost < 1, "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("Output.txt"));
         Debug.Listeners.Add(tr2);
         
 
         Debug.WriteLine("The product name is "+sProdName);
         Debug.WriteLine("The available units on hand are"+iUnitQty);
         Debug.WriteLine("The per unit cost is "+dUnitCost);
         Debug.Unindent();
         Debug.WriteLine("Debug Information-Product Ending");
         Debug.Flush();
         
         Trace.WriteLine("Trace Information-Product Starting ");
         Trace.Indent();

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

         Trace.Unindent();
         Trace.WriteLine("Trace Information-Product Ending");

         Trace.Flush();

         Console.ReadLine();
      }			
   }
注意:要使此代码示例发挥作用,必须通过将 using System.Diagnostics; 粘贴为第一行代码来添加 System.Diagonstics 名称空间。

疑难解答

如果解决方案配置类型是 Release,则会忽略 Debug 类输出。
在为特定目标创建 TextWriterTraceListener 类后,TextWriterTraceListener 会从 Trace 类和 Debug 类接收输出。无论您是否使用TraceDebug 类的 Add 方法将 TextWriterTraceListener 添加到 Listeners 类,都会出现这种情况。
如果将同一目标的 Listeners 对象添加到 Trace 类和 Debug 类中,则无论是 Debug 类还是 Trace 类生成输出,各行输出都会重复出现。
         TextWriterTraceListener myWriter = new TextWriterTraceListener(System.Console.Out);
         Debug.Listeners.Add(myWriter);
        
         TextWriterTraceListener myCreator = new TextWriterTraceListener(System.Console.Out);
         Trace.Listeners.Add(myCreator);
         

参考

有关详细信息,请参阅 .NET Framework 类库文档中的下列主题:
Trace 类
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfSystemDiagnosticsTraceClassTopic.asp (http://msdn.microsoft.com/library/en-us/cpref/html/frlrfSystemDiagnosticsTraceClassTopic.asp)

Debug 类
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfSystemDiagnosticsDebugClassTopic.asp (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfSystemDiagnosticsDebugClassTopic.asp)


有关跟踪的详细信息,请参阅 Microsoft GotDotNet 快速入门教程中的以下主题:
如何使用跟踪?
http://samples.gotdotnet.com/quickstart/howto/doc/Trace.aspx (http://samples.gotdotnet.com/quickstart/howto/doc/Trace.aspx)
只有注册用户登录后才能发表评论。