The TraceSwitch and BooleanSwitch classes are two built-in classes that provide trace switch functionalities. If you need different trace levels or different implementations of the Switch class, you can inherit from the Switch class and implement your own custom trace switch.
In this exercise, I show you how to create a custom trace switch. I will create a FactorialSwitch class that can be set with four values ( Negative [ -1 ], Off [ ], Overflow [ 1 ] and Both [ 2 ]) for the Factorial Calculator form. The class will have two properties, Negative and Overflow.
Estimated time : 25 minutes.
Launch Visual Studio .NET, Select File, New, Blank Solution and name the new solution 310C09Exercises .
Add a new Windows application project to the solution. Name the project Exercise9-1 .
Delete Form1.vb from the new project.
Follow the directions from Step By Step 9.1 to create a copy of the FactorialCalculator.vb form in this project.
Add a new class to the project. Name the class FactorialSwitch.vb and modify the class definition with the following code:
Imports System Imports System.Diagnostics Public Enum FactorialSwitchLevel Negative = -1 Off = 0 Overflow = 1 Both = 2 End Enum Public Class FactorialSwitch Inherits Switch Public Sub New(_ ByVal DisplayName As String, _ ByVal Description As String) MyBase.New(DisplayName, Description) End Sub Public Property Negative() As Boolean Get ' Return true if the ' SwitchSetting ' is Negative or Both If ((SwitchSetting = -1) Or _ (SwitchSetting = 2)) Then Return True Else Negative = False End If End Get Set(ByVal Value As Boolean) End Set End Property Public Property Overflow() As Boolean Get ' Return true if the ' SwitchSetting ' is Overflow or Both If ((SwitchSetting = 1) Or _ (SwitchSetting = 2)) Then Return True Else Negative = False End If End Get Set(ByVal Value As Boolean) End Set End Property End Class
Open FactorialCalculator.vb in code view. Change the Click event handler of the btnCalculate control as follows :
Private Sub btnCalculate_Click(_ ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles btnCalculate.Click Dim facSwitch As FactorialSwitch = _ New FactorialSwitch("FactorialTrace", _ "Trace the factorial application") Dim intNumber As Integer = _ Convert.ToInt32(txtNumber.Text) If facSwitch.Negative Then ' Make a debug assertion Debug.Assert(intNumber >= 0, _ "Invalid value", _ "negative value in debug mode") End If Dim intFac As Integer = 1 Dim i As Integer Try For i = 2 To intNumber intFac = intFac * i Next Catch ex As Exception If facSwitch.Overflow Then ' Write a debug message ' if the condition is true Debug.WriteLineIf(intFac < 1, _ "There was an overflow", _ "Factorial Program Debug") End If End Try txtFactorial.Text = intFac.ToString() End Sub
In the Solution Explorer, select Show All Files from the toolbar. Navigate to the bin folder. Right-click on this folder to select Add, Add New Item. Choose to create an XML file; name the XML file as Exercise9-1.exe.config.
In the XML editor, type the following configuration data in the XML file.
<?xml version="1.0" encoding="utf-8" ?> <configuration> <system.diagnostics> <switches> <add name="FactorialTrace" value="2" /> </switches> </system.diagnostics> </configuration>
Set the form as the startup form for the project and set the project as the startup project for the solution.
Run the project using the default Debug configuration. You will notice that the Negative assertion dialog box is displayed only if the switch is set with values 1 or 2 . Similarly, the Overflow message is displayed in the Output window only if the switch value is set to 1 or 2 .
The value set in the configuration file can be accessed through the SwitchSetting property of the Switch class. The Negative and Overflow properties of the FactorialSwitch class return True or False , depending on the value of the SwitchSetting property.
You can perform step-by-step execution of SQL Server stored procedures in Visual Basic .NET. This exercise shows you how.
Estimated time : 30 minutes
Add a new Windows application project to the solution. Name the project Exercise9_2 .
Rename the Form1.vb form MostExpensiveProducts.vb . Switch to code view and change all occurrences of Form1 to MostExpensiveProducts .
Select Project, Properties from the main menu. Select Debugging under the Configuration Properties node in the left pane of the Property Pages window. Change the configuration to Active(Release). In the right pane, under the Debuggers node, choose the check box to enable SQL Server debugging, as shown in Figure 9.41.
Drag a SqlDataAdapter component to the form from the Data tab of the toolbox. This activates the Data Adapter Configuration Wizard. Click Next. Select the Northwind database connection that you have already created in the earlier chapters or click the New Connection button to create a Northwind database connection. Click Next.
Choose the Use Existing Stored Procedures option in the Choose a Query Type page. Click Next. Select Ten Most Expensive Products from the Select combo box, as shown in Figure 9.42. Click Next and then click Finish. A SqlDataAdapter component and a SqlConnection component are created in the component tray.
Select the SqlDataAdapter1 component, and then right-click and select Generate DataSet from the context menu. Select the New radio button and choose Ten Most Expensive Products (SqlDataAdapter1) from the checked list box. Click OK to create a DataSet11 component in the component tray.
Place a Button control ( btnGetProducts ) and a DataGrid control ( DataGrid1 ) on the form. Change the DataGrid control's DataSource property to DataSet11 and DataMember property to Ten Most Expensive Products .
Add the following code to the Click event of the Button control:
Private Sub btnGetProducts_Click(_ ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles btnGetProducts.Click SqlDataAdapter1.Fill(DataSet11) End Sub
Insert a breakpoint in the Click event handler at the point of a call to the Fill() method of the sqlDataAdapter1 object.
Open Server Explorer. Open the Data Connections node and select the stored procedure Ten Most Expensive Products. You can find this stored procedure by drilling into the tree, starting with the Data Connections node, and then the node for the current connection, and then the Stored Procedures folder. Right-click the stored procedure and select Edit Stored Procedure. Insert a breakpoint in the starting code line of the stored procedure, as shown in Figure 9.43.
Set the form as the startup object for the project. Run the project. Click the button. The program starts step-by-step execution as soon as it encounters the breakpoint in the Fill() method call line. Press F8. You are taken to the stored procedure code where you can perform step-by-step execution.
This exercise teaches you how to debug SQL Server stored procedures by using step-by-step execution. In Figure 9.43, notice the outline enclosing the SELECT statement. The outline encloses a single debugging step.
Watching SQL Server Variables You can use various tools, such as the Watch and Locals windows, to keep track of the values of the variables defined in the stored procedures during step-by-step execution. These tools are very helpful when you are debugging complex stored procedures.
For what do you use a test plan?
A test plan is a document that guides the process of testing. This document should clearly specify the different approaches to testing, the test cases, the validation criteria of the tests, and so on.
What is the purpose of the Assert() method in the Debug and Trace classes?
The Assert() method takes a condition as its first parameter and then displays an Assertion Failed dialog box if the condition evaluates to false .
What is the main purpose of TraceListener class? What classes implement TraceListener in the Framework Class Library?
TraceListener is an abstract class that provides functionality for receiving trace and debug messages. DefaultTraceListener , TextWriterTraceListener , and EventLogTraceListener are the three built-in classes that implement TraceListener .
What are the two built-in trace switches in the .NET Framework Class Library?
The two built-in trace switches in the .NET Framework Class Library are BooleanSwitch and TraceSwitch .
What is the main advantage of trace switches?
You can easily change the value of trace switches by editing the application configuration (XML) file, using any text editor. To make these changes take effect, you need not recompile the application; you just need to restart it.
What types of methods can be marked with the Conditional attribute?
Before you can apply the Conditional attribute to a method, the method should be a Sub rather than a Function.
What three commands can you use to step through code while debugging?
The three commands that allow you to step through code are Step Into (steps into each statement of the method called), Step Over ( performs the entire method call in one step), and Step Out (steps out of the method call).
What happens when you put a breakpoint in code?
When the debugger encounters a breakpoint in code, it pauses the execution of the application. The execution can be resumed via the stepping commands.
What are some of the different windows available for debugging?
Visual Studio .NET provides a variety of windows to ease the debugging process. Some of these windows are Me, Locals, Autos, Watch, Call Stack, and Breakpoints.
How can you attach the debugger to a running process in Visual Basic .NET?
To attach the debugger to a running process, open Visual Basic .NET, invoke the Processes dialog, select the process from the list of processes, and click the Attach button.
In order to verify that remote debugging is enabled on a system, what should you check?
You should verify that the remote machine has Machine Debug Manager ( mdm.exe ) running as a background process to enable debugging support. You should also verify that you are a member of the Debugger Users group in order to remotely access the machine for debugging.
How can you debug an already running COM+ (Enterprise Services) application?
To debug a COM+ library application, you must attach a debugger to the process in which the client application is running. On the other hand, to debug a COM+ server application, you must attach a debugger to the dllhost.exe process in which the COM+ server application is running.
Which of the following activities correctly defines a typical unit test?
C. A unit test involves running a module against carefully planned test data and checking whether it works according to its specification. Debugging is the process of locating and fixing errors. When you run a complete application against test data, you are performing system testing. Checking whether the modules integrate well is part of integration testing.
You are creating a .NET remoting object. You want to add code to the object to log error messages and warning messages. You want to log messages to both a log file and to the Windows application log but do not want a message to be duplicated . Which of the following code segments should you use?
C. To log messages to custom target locations, you need to add custom listeners to the Trace.Listeners collection. This eliminates choices A and D. In between B and C, C is correct because you want to log a message only once.
You are developing a Windows application that heavily uses SQL Server stored procedures. You are debugging a Windows form that calls the YTDSales stored procedure. The stored procedure uses a variable named @Sales. You want to see how the value of this variable changes as the code in the stored procedure executes. Which of the following options will allow you to do this?
D. You can use the Locals window to keep track of the values of the variables defined in the Stored Procedures during its step-by-step execution.
In your Visual Basic .NET program, you have the following lines of code:
Dim MyTraceSwitch As TraceSwitch = _ New TraceSwitch(_ "SwitchOne", "The first switch") MyTraceSwitch.Level = TraceLevel.Info
Which of the following expressions in your program would evaluate to false ?
D. Setting the Level property of TraceSwitch to TraceLevel.Info allows it to capture all informational, warning, and error messages, but not the verbose messages. Thus, the TraceInfo , TraceWarning , and TraceError properties of the switch evaluate to True but the TraceVerbose property evaluates to False .
You are developing a retail Web site for selling ready-made garments. Your application has a collection of serviced components that executes the business logic. All the serviced components are marked with the Transaction(TransactionOption.Required) attribute. All the methods in the components are marked with the AutoComplete attribute. While testing the application, you find that inventory is not being updated properly. When you attempt to debug the application, a System.Runtime.InteropServices.COMException is thrown. The exception includes the following message: "The root transaction wanted to commit, but transaction aborted." You also find that this exception occurs only during the debugging session, and not when the components run outside of the debugger. You need to resolve this problem so that you can debug the application to find the problem with inventory updates. Which of the following options should you select to resolve this problem?
C. When you debug a program, the transaction might not complete in the set timeframe (the default is 60 seconds). In that case, the program will throw the given exception. Because you have a bunch of components here, instead of setting the transaction timeout value for each of them individually, you can set the transaction timeout property for the applications running the computer.
You are asked to implement tracing in an XML Web service such that the application should display both warning and error messages when the application is run by using the Debug configuration, but should display only error messages when it is run by using the Release configuration. Which of the following code segments best meets this requirement?
A. In answer A, for the Debug configuration where the DEBUG symbol is defined, the Level property of traceSwitch is set to TraceLevel.Warning . This causes both the TraceWarning and TraceError properties of this object to evaluate to True in the Debug configuration, causing both of the messages to be displayed. In the Release configuration, where only the TRACE symbol is defined, the Level property of traceSwitch is set to TraceLevel.Error . This causes the TraceWarning property to result in a False value and the TraceError property to return a True value, causing only the error messages to be displayed.
The configuration file of an XML Web service has the following contents:
<system.diagnostics> <switches> <add name="BooleanSwitch" value="-1" /> <add name="TraceLevelSwitch" value="33" /> </switches> </system.diagnostics>
You are using the following statements to create switch objects in your code:
Dim bs As BooleanSwitch = _ New BooleanSwitch(_ "BooleanSwitch", "Boolean Switch") Dim ts As TraceSwitch = _ New TraceSwitch(_ "TraceLevelSwitch", "Trace Switch")
Which of the following options is correct regarding the values of these switch objects?
B. For BooleanSwitch , a value of corresponds to Off , and any nonzero value corresponds to On . For TraceSwitch any number greater than 4 is treated as Verbose . From the given values in the configuration file, the booleanSwitch object should have its Enabled property set as true , and the traceSwitch object should have its Level property set to TraceLevel.Verbose .
You are developing a Windows application. Your application's configuration files have the following code:
<system.diagnostics> <switches> <add name="TraceLevelSwitch" value="3" /> </switches> </system.diagnostics>
You have written the following tracing code in your program:
Dim ts As TraceSwitch = New TraceSwitch(_ "TraceLevelSwitch", _ "Trace the application") <Conditional("DEBUG")> _ Private Sub Method1() Trace.WriteLineIf(ts.TraceError, "Message 1", "Message 2") End Sub <Conditional("TRACE")> Private Sub Method2() Trace.WriteLine("Message 3") End Sub Private Sub btnCalculate_Click(_ sender As Object, _ e As System.EventArgs e) _ Handles btnCalculate.Click If ts.TraceWarning Then Trace.WriteLine("Message 10") Method1() Else Trace.WriteLineIf(ts.TraceInfo, _ "Message 20") Method2() End If If ts.TraceError Then Trace.WriteLineIf(_ ts.TraceInfo, "Message 30") End If Trace.WriteLineIf(ts.TraceVerbose, _ "Message 40") End Sub
What tracing output would be generated if you ran your program in Debug mode and clicked the btnCalculate button?
B. The XML file has 3 as the value for TraceLevelSwitch , which causes the Level property to be set to TraceLevel.Info . This causes the TraceError , TraceWarning , and TraceInfo properties of the traceSwitch to be true ; only the TraceVerbose property evaluates to false . Also, the third parameter of the WriteLineIf () method is used to categorize the output by specifying its value followed by a colon ( : ) and then the trace message.
You have the following segment of code in your program:
Dim tl As EventLogTraceListener = _ New EventLogTraceListener("TraceLog") Trace.Listeners.Add(tl) Debug.Listeners.Add(tl) Trace.WriteLine("Sample Message") Debug.WriteLine("Sample Message")
When you debug the program through Visual Studio .NET, how many times would the message "Sample Message" be written to the trace log?
D. The message SampleMessage will be written four times. This is because two instances of EventLogTraceListeners are added to the Listeners collection. Any message generated by the Trace and Debug classes will be listed twice. Because the program is running in the Debug mode, both the Trace and Debug statements will be executed. The net effect is that both the Trace.WriteLine and Debug.WriteLine messages will be written twice, making four entries in the trace log.
Which of the following statements are true for the remote debugging of processes? (Select two.)
B, D. For remote debugging, Visual Studio .NET is not required on the remote machine. In this case, you need to run Remote Components Setup on the remote machine. You need to have Visual Studio .NET on the local machine in order to debug the remote processes.
While you are debugging in Visual Studio .NET, you want to watch the value of only those variables that are in use in the current and previous statements. Which of the following debugger windows is the easiest window to use to watch these variables?
A. The Autos window gives you the most convenient access because it automatically displays names and values of all variables in the current statement and the previous statement at every step.
You are debugging a Windows form. The form involves long calculation and iterations. You want to break into the code to watch the value of variables whenever the value of intValue changes in the following statement:
intValue = ProcessValue(intValue)
Which of the following options will quickly allow you to achieve this?
D. When you want to break into the code when a value of a variable changes, the quickest approach is to set a conditional breakpoint where you specify the variable name and check the Has Changed option.
You want to debug a remote process. The remote machine does not have Visual Studio .NET installed on it. Which of the following options should you choose?
A. To debug a remote process, the process first needs to be started on the remote machine. You can then open Visual Studio .NET on the local machine and attach the debugger to the running process. After the debugger is attached, you can break into the code of the remote process and do step-by-step execution or set a breakpoint.
You create a serviced component named ConnectionDispenser . This component is stored in the DbUtils.dll assembly and is registered in the COM+ catalog. The serviced component is configured to be activated as a library application. You discover that the CreateNewConnection() method is not working as expected. You want to debug any calls to this method. What should you do?
B. A serviced component activated as a library application runs in the process of its caller. Therefore, to debug such an application, you can set a breakpoint in the client application and then step into the serviced component code.
You want to debug a remote process running on a Windows 2000 Server computer that is not in the domain of your local computer. The remote server has a full installation of Visual Studio .NET. The two domains do not have two-way trust established, but you do have a username and password on the remote Windows 2000 server. Which of the following would allow you to debug a process on that machine?
C. If your local machine's domain does not have a two-way trust relationship with the remote computer's domain, you cannot debug a remote process. The only option you have is to log on to the remote machine by using Terminal Server, start Visual Studio .NET on the remote machine, and use Visual Studio .NET to attach the debugger to the process that is running on the same machine. You then debug as if you were debugging a process running on your local machine.
You are trying to debug a Windows application using Visual Studio .NET installed on your local machine. The Windows application is deployed on a remote server. When you attempt to debug the application, you get a DCOM configuration error. Which of the following steps should you take to resolve this problem?
D. If you get a DCOM configuration error while debugging, possibly you are not a member of the Debugger Users group on the remote machine. To resolve this, add your account on the remote machine to the Debugger Users group.
1. Windows Forms QuickStart Tutorial:
Diagnostics topics in the "How Do I" section.
Debugging topics in the "How Do I" section.
2. Visual Studio .NET Combined Help Collection:
"Introduction to Instrumentation and Tracing."
"Using the Debugger."
3. Kevin Burton. .NET Common Language Runtime Unleashed . Sams, 2002.
4. Richard Grimes. Developing Applications with Visual Studio .NET . Addison-Wesley, 2002.