Evjen c24.tex V2 - 01/28/2008 3:40pm Page 1120 Chapter 24: Debugging and Error Handling Listing 24-3: Using diagnostic switches <configuration> <system.diagnostics> <switches> <add name="ImportantSwitch" value="1" /> <! This is for the BooleanSwitch > <add name="LevelSwitch" value="3" /> <! This is for the TraceSwitch > <add name="SourceSwitch" value="4" /> <! This is for the SourceSwitch > </switches> </system.diagnostics> </configuration> Switches can be used in an if statement for any purpose, but they are most useful in the context of tracing along with System.Diagnostics.Trace.WriteIf : VB Dim aSwitch As New BooleanSwitch("ImportantSwitch", "Show errors") System.Diagnostics.Trace.WriteIf(aSwitch.Enabled, "The Switch is enabled!") C# BooleanSwitch aSwitch = new BooleanSwitch("ImportantSwitch", "Show errors"); System.Diagnostics.Trace.WriteIf(aSwitch.Enabled, "The Switch is enabled!"); If ImportantSwitch is set to 1 , or a non-zero value, in the config file, the call to WriteIf sends a string to trace output. TraceSwitch TraceSwitch offers five levels of tracing from 0 to 4, implying an increasing order: Off, Error, Warning, Info, and Verbose. You construct a TraceSwitch exactly as you create a BooleanSwitch : VB Dim tSwitch As New TraceSwitch("LevelSwitch", "Trace Levels") System.Diagnostics.Trace.WriteIf(tSwitch.TraceInfo, "The Switch is 3 or more!") C# TraceSwitch tSwitch = new TraceSwitch("LevelSwitch", "Trace Levels"); System.Diagnostics.Trace.WriteIf(tSwitch.TraceInfo, "The Switch is 3 or more!"); A number of properties on the TraceSwitch class return true if the switch is at the same level or at a higher level than the property’s value. For example, the TraceInfo property will return true if the switch’s value is set to 3 or mo re. SourceSwitch New with .NET 2.0 is SourceSwitch , which is similar to TraceSwitch but provides a greater level of granularity. You call SourceSwitch.ShouldTrace with an EventType as the parameter: VB Dim sSwitch As New SourceSwitch("SourceSwitch", "Even More Levels") 1120 Evjen c24.tex V2 - 01/28/2008 3:40pm Page 1121 Chapter 24: Debugging and Error Handling System.Diagnostics.Trace.WriteIf(sSwitch.ShouldTrace(TraceEventType.Warning), _ "The Switch is 3 or more!") C# SourceSwitch sSwitch = new SourceSwitch("SourceSwitch", " Even More Levels"); System.Diagnostics.Trace.WriteIf(sSwitch.ShouldTrace(TraceEventType.Warning), "The Switch is 4 or more!"); Web Events It doesn’t exactly qualify as debugging, but a series of new application-monitoring and health-monitoring tools within the system has been added in ASP.NET’s System.Web.Management namespace in ASP.NET 2.0. These tools can be as valuable as tracing information in helping you monitor, maintain, and diagnose the health of your application. The system has a whole new event model and event engine that can update your application with runtime details. There are a number of built-in events, including application lifetime events such as start and stop and a heartbeat event. You can take these base classes and events and build on them to create events of your own. For example, you might want to create an event that tells you when a user downloads a particularly large file or when a new user is created in your personalization database. You can have your application send an e-mail to you once a day with statistics. For instance, you can create your own event by deriving from System.Web.Management.WebBaseEvent , as shown in Listing 24-4. Listing 24-4: Web events VB Imports System Imports System.Web.Management Namespace Wrox Public Class WroxEvent Inherits WebBaseEvent Public Const WroxEventCode As Integer = WebEventCodes.WebExtendedBase + 1 Public Sub New(ByVal message As String, ByVal eventSource As Object) MyBase.New(message, eventSource, WroxEventCode) End Sub End Class End Namespace C# namespace Wrox { using System; using System.Web.Management; public class WroxEvent: WebBaseEvent { public const int WroxEventCode = WebEventCodes.WebExtendedBase + 1; public WroxEvent(string message, object eventSource) : base(message, eventSource, WroxEventCode){} } } 1121 Evjen c24.tex V2 - 01/28/2008 3:40pm Page 1122 Chapter 24: Debugging and Error Handling Later, in a sample Page_Load , you raise this event to the management subsystem: VB Protected Sub Page_Load(sender As Object, e As EventArgs) ’ Raise a custom event Dim anEvent As Wrox.WroxEvent = New Wrox.WroxEvent("Someone visited here", Me) anEvent.Raise() End Sub C# protected void Page_Load(Object sender, EventArgs e) { // Raise a custom event Wrox.WroxEvent anEvent = new Wrox.WroxEvent("Someone visited here!", this); anEvent.Raise(); } The event is caught by the management subsystem and can be dispatched to different providers based on a number of rules. This is a much more formal kind of tracing than a call to Trace.WriteLine ,soyou create a strongly typed event class for events specific to your application: Web.config <?xml version="1.0"?> <configuration> <system.web> <healthMonitoring enabled="true"> <providers> <add name="WroxDatabaseLoggingProvider" type="System.Web.Management.SqlWebEventProvider" connectionStringName="QuickStartSqlServer" maxEventDetailsLength="1073741823" buffer="false"/> </providers> <rules> <add name="Application Lifetime Events Rule" eventName="All Events" provider="WroxDatabaseLoggingProvider" profile="Critical" /> </rules> </healthMonitoring> </system.web> </configuration> Debugging Visual Studio includes two configurations by default: debug and release. The debug configuration auto- matically defines the debug and trace constants, enabling your application to provide context to a troubleshooter. The option to generate debugging information is turned on by default, causing a pro- gram database (or debug) file (PDB) to be generated for each assembly and your solution. They appear in the same \ bin folder as your assemblies. Remember, however, t hat the actual compilation to native code does not occur in Visual Studio, but rather at runtime using just-in-time compilation (JIT). The JIT will automatically optimize your code for speed. Optimized code, however, is considerably harder to debug 1122 Evjen c24.tex V2 - 01/28/2008 3:40pm Page 1123 Chapter 24: Debugging and Error Handling because the operations that are generated may not correspond directly to lines in your source code. For debug purposes, this option is set to false . What’s Required The PDBs are created when either the C# compiler ( CSC.EXE ) or Visual Basic compiler ( VBC.EXE )is invoked with the /debug:full command lines switch. As an option, if you use /debug:pdbonly ,you will generate PDBs but still direct the compiler to produce release-mode code. Debug versus Release The debug and release configurations that come with Visual Studio are generally sufficient for your needs. However, these configurations control only the compilation options of the code behind files. Remember that, depending on how you’ve chosen to design your ASP.NET application, the ASP.NET .aspx files may be compiled the first time they’re hit, or the entire application may compile the first time a page is hit. You can control these compilation settings via the compilation elements within the < system.web > section of your application’s web.config .Set< compilation debug="true" > to produce binaries as you do when using the /debug:full switches. PDBs are also produced. The average developer is most concerned with the existence of PDB files. When these files exist in your ASP.NET applications \ bin folder, the runtime provides you with line numbers. Of course, line numbers greatly assist in debugging. You can’t step through source code during an interactive debugging session without these files. An interesting CLR Internals trick: Call System.Diagnostics.Debugger.Launch within your assembly, even if the assembly was compiled via /debug:pdbonly ,and the debugger pops up. The JIT compiler compiles code on the first call to a method, and the code that it generates is debuggable because JIT knows that a debugger is attached. Debugging and the JIT Dialog When an unhandled error occurs in an ASP.NET application, the default error handler for the ASP.NET worker process catches it and tries to output some HTML that expresses what happened. However, when you are debugging components outside of ASP.NET, perhaps within the context of unit testing, the debug dialog box appears when the .NET application throws an unhandled exception. If something has gone horribly wrong with an ASP.NET application, it’s conceivable that you may find a Web server with the dialog box popped up waiting for your input. This can be especially inconvenient if the machine has no keyboard o r monitor hooked up. The day may come when you want to turn off the debug dialog box that appears, and you have two options to do this: ❑ You can disable JIT Debugging from the registry. The proper registry key is HKLM \ Software \ Microsoft \ .NETFramework \ DbgJITDebugLaunchSetting . There are three possible values for the option: ❑ 0 : Prompts the user by means of a message box. The choices presented include Continue, which results in a stack dump and process termination, and Attach a Debugger, which means the runtime spawns t he debugger listed in the DbgManagedDebugger registry key. If no key e xists, the debugger releases control and the process is terminated. 1123 Evjen c24.tex V2 - 01/28/2008 3:40pm Page 1124 Chapter 24: Debugging and Error Handling ❑ 1 : Does not display a dialog box. This results in a stack dump and then process termination. ❑ 2 : Launches the debugger listed in the DbgManagedDebugger registry key. For this option, the registry entry must to be set to 0 for the dialog box to show up. ❑ To disable the JIT debug dialog box and still present an error dialog box, within Visual Stu- dio.NET, choose Tools ➪ Options ➪ Debugging ➪ Just-In-Time and deselect Common Language Runtime. Instead of the Select a Debugger dialog box, an OK/Cancel dialog box will appear during an unhandled exception. IIS versus ASP.NET Development Server ASP.NET greatly simplifies your Web developing experience by enabling you to develop applications without IIS (Internet Information Server — the Web server) on your developer machine. Rather than the traditional style of creating a virtual directory and mapping it to a physical directory, a directory can be opened as a Web site simply by telling Visual Studio that it is a Web site. When you open a Web site from the File menu, the first option on the list of places to open from is the file system. Visual Studio considers any folder that you open to be the root of a Web site. Other options, of course, are opening Web sites from your local IIS instance, FTP, or source control. Using the IIS option works much as it does in previous versions of Visual Studio with a few convenient changes such as the capability to create a Web site o r map a virtual directory directly from the Open Web Site dialog. However, more interesting stuff happens after you open a Web site from the file system. By default, Web sites that exist only on the file system have a ‘‘just-in-time’’ Web server instantiated called the ASP.NET Development Server. The small Web server hosts the exact same ASP.NET page rendering at runtime that is hosted within IIS on a deployed production site. The page rendering behavior should be identical under the small server as it is under IIS. You should be aware of a few important differences and specific caveats to ensure a smooth transition from development to production. Create a new Web site by selecting File ➪ New Web Site and immediately pressing F5 to begin a debug- ging session. You are greeted with a Debugging Not Enabled dialog box. The first option automatically adds a new web.config file with debugging enabled. (Earlier versions of Visual Studio required a tedious manual pro ce ss.) Click OK a nd balloon help appears in the system tray announcing that the ASP.NET Development Server has started up. It also shows what random high-number port the Web server has selected on the local host. When you close your browser and stop your debugging session, the tiny Web server shuts down. The ASP.NET Development Server is an application, not a service. It is not a replacement for IIS, nor does it try to be. It’s really just a broker that sits between the developer and the ASP.NET page renderer, and it contains very few, if any, of the security benefits that IIS includes. It is loosely based on a .NET 1.x project, code-named Cassini, which is downloadable from http://asp.net/Projects/Cassini/Download/ Default.aspx . This project was a sample meant to illustrate how to use the System.Web.Hosting name- space. The Cassini project was the grandparent, and now the ASP.NET Development Server is a first-class member of the Visual Studio product family. Including this tiny Web server with the Development Environment also allows Visual Studio to be used on Windows XP Home systems that are unable to run IIS. 1124 Evjen c24.tex V2 - 01/28/2008 3:40pm Page 1125 Chapter 24: Debugging and Error Handling The small Web server runs under the same user context that runs Visual Studio. If your application requires a specific security context, such as an anonymous user or specific domain user, consider using IIS as your development Web server. Additionally, because the Web server starts up on a port other than port 80, be sure to use best practices while developing your site’s navigation scheme. Often, developers assume their site’s URL will not include a port number (it will default to port 80), that their site may appear within a specific subdomain ( bar.foo.com ), or that their site will appear within a subdirectory ( www.foo.com/bar ). Consider making your navigation relative to the virtual root of your application so your application is resilient enough to be run in many contexts. Starting a Debugging Session There are a number of ways to enter an interactive debugging session with ASP.NET. Visual Studio can fire up the ASP.NET Worker Process, load your newly compiled Web site and attach t he debugging to the Worker Process automatically. Or, you can attach a debugger to a site that is already running. Visual Studio also includes a new simpler remote debugging tool for cross-machine debugging. F5 Debugging When you start debugging an ASP.NET application, Visual Studio takes into consideration all the Start options within your project properties. Just as ASP.NET 1.x Visual Studio can be set to launch the browser on a specific page, the new version allows you to start debugging using the currently selected page. The specific page has been selected so that the Visual Studio debugger can automatically attach the correct process, which might be the Visual Studio Web Server, the ASP.NET Worker Process, or a remote debug monitor. Attaching to a Process It’s often convenient to jump into an interactive debugging session of a Web site that is already running, and at known state, rather than starting an application from scratch each time you debug. To begin debugging a site that is already running, f rom Visual Studio’s Debug menu, select Attach to Process. The dialog has been improved from previous versions of Visual Studio and now includes a Refresh button and simplifies most common debugging use cases by showing only those processes t hat belong to the user and that are in the currently running session. Also included is a transport drop-down with the default transport selected. The default allows you to select processes on your computer or on a remote computer that’s running the Remote Debugging Monitor. Other options are there for smart client or unmanaged debugging. The only difference between starting a Debug session via F5 and attaching to a process manually is that when you debug via F5, Visual Studio automatically starts up a browser or external application for you. Remember that if you use Attach to Process, it is assumed that you have already done the work of starting up the process. The ASP.NET Worker Processes under IIS will start up when the site has been hit with an HttpRequest at least once. The debugger can now attach to the running Worker Process. Sometimes you want to debug an ASP.NET application that is already running on your computer. If that application was not started by Visual Studio and you want to attach to it, select Attach to Process from the Debug menu and choose either ASPNET_WP.exe (if you’re running Windows XP) or W3WP.exe (if you are running Windows 2003 server). Be careful that you are not trying to debug an application that is actively servicing other users or you may ruin their experience. 1125 Evjen c24.tex V2 - 01/28/2008 3:40pm Page 1126 Chapter 24: Debugging and Error Handling Simpler Remote Debugging Remote debugging got simpler with Visual Studio 2005. However, in the interest of security, you must have the appropriate credentials to perform remote debugging. Y ou’ll find a Remote Debugger folder in C: \ Program Files \ Microsoft Visual Studio 8 \ Common7 \ IDE . In Figure 24-10, Explorer is shown open and the Remote Debugger folder is selected and has been configured as a shared directory for access over the local network. Figure 24-10 To begin, remote debugging must be set up on the machine that contains the application you want to debug. Rather than performing a complicated installation, you can now use the Remote Debug Monitor, and an application that can simply be run off a file share. The easiest scenario has you sharing these components directly from your Visual Studio machine and then running msvsmon.exe off the share, as shown in Figure 24-11. Simply running the Remote Debug Monitor executable off the file share can make remote ASP.NET debugging of an already-deployed applications much simpler, although you still need to manually attach to the ASP.NET worker process because automatic attaching is not supported. Do note that there are now 1126 Evjen c24.tex V2 - 01/28/2008 3:40pm Page 1127 Chapter 24: Debugging and Error Handling two versions of the debugger, one for x86 processes and one for x64 processes, so make sure you’re using the right debugger for your process. Figure 24-11 You are allowed to debug a process that’s running under your account and password without any special permissions. If you need to debug a process running under another account name, such as an ASP.NET worker process running as a user who is not you, you must be an administrator on the machine running the process. The most important thing to remember when debugging remotely is this: You need to get the user account that is running as Visual Studio to map somehow to a legitimate user account on the machine running the Remote Debug Monitor ( msvsmon.exe ) machine and vice versa. The easiest way to do this is to create a local user account on both computers with the same username and password. To run msvsmon as a user other than Visual Studio, you must create two user accounts on each computer. If one of the machines is located on a domain, be aware that domain account can be mapped to a local account. You create a local user account on both computers. However, if you pick the same username and password as your domain account, Visual Studio can be run as a domain account. Figure 24-12 shows 1127 Evjen c24.tex V2 - 01/28/2008 3:40pm Page 1128 Chapter 24: Debugging and Error Handling the machine name is SCOTTPC and the username is Wrox. A Wrox user was created on both machines with the same password on each. For Windows XP machines on a workgroup, the security option entitled Network Security: Shared and Security Model for Local Accounts affects your use of the Remote Debug Monitor. If this option is set to Guest Only — Local Users Authenticate As Guest, then remote debugging fails and shows you a dialog box. Configure this via the Local Security Policy MMC-based administrative tool. The warning doesn’t affect Windows 2000 or Windows Server 2003, Windows XP, or Vista-based computers that are joined to a domain. Figure 24-12 Debugging Running Windows XP Service Pack 2 Make sure that TCP Port 80 is set to allow ASP.NET and IIS to communicate with the remote machine. Try to keep the scope limited, using options such as Local Subnet Only, and avoid exposing your Web server to the Internet during development. Also include TCP Port 135, which allows DCOM to communi- cate with remote machines as well as with UDP Ports 4500 and 500 for IPSec-based security. Last, confirm that the Remote Debug Monitor ( msvsmon.exe ) is in the list of exceptions to the firewall. Again, avoid exposing your debugging session to the outside world. Remote debugging is usually a last resort if the bug isn’t reproducible for whatever reason on the developer workstation. New Tools to Help You with Debugging The debugging experience in Visual Studio has improved arguably more than any other aspect of the environment. A number of new tools, some obvious, some more subtle, assist you in every step of the debug session. Debugger Datatips Previous versions of Visual Studio gave you tooltips when the user hovered the mouse over variables of simple types. Visual Studio 2005 offers datatips, allowing. complex types to be explored using a modeless tree-style view that acts like a tooltip and provides much more information. After you traverse the tree to the node that you’re interested in, that simple type can be viewed using a visualizer by clicking the small magnifying glass icon, as seen in Figure 24-13. 1128 Evjen c24.tex V2 - 01/28/2008 3:40pm Page 1129 Chapter 24: Debugging and Error Handling Figure 24-13 Data Visualizers As you see in Figure 24-13, a simple type can be viewed using any number of data visualizers. For example, if a simple variable such as a string contains a fragment of XML, you might want to visualize that data in a style that’s more appropriate for the data’s native format, as shown in Figure 24-14. Figure 24-14 The visualizers are straightforward to write and, although Visual Studio ships with default visualizers for t ext, HTML, XML, and DataSets, expect to see a flood of new visualizers appearing on the Internet with support for images, collection classes, and more. The result is a rich, unparalleled debugging experience. 1129 . system has been added in ASP. NET s System.Web.Management namespace in ASP. NET 2.0. These tools can be as valuable as tracing information in helping you monitor, maintain, and diagnose the health. cross-machine debugging. F5 Debugging When you start debugging an ASP. NET application, Visual Studio takes into consideration all the Start options within your project properties. Just as ASP. NET 1.x Visual. appear during an unhandled exception. IIS versus ASP. NET Development Server ASP. NET greatly simplifies your Web developing experience by enabling you to develop applications without IIS (Internet Information