March 24, 2009, 6:52 a.m.
posted by fractal
Debugging
Debugging is the process of finding the causes of errors in a program, locating the lines of code that are causing those errors, and fixing those errors. Without tools, the process of debugging can be very time-consuming and tedious. Thankfully, Visual Studio .NET comes loaded with a large set of tools and features to help you with various debugging tasks. Some of these features include
NOTE Runtime Errors and Compile-Time Errors Compile-time errors are produced when a program does not comply with the syntax of the programming language. These errors are trivial and are generally pointed out by compilers themselves. Runtime errors occur in programs that are compiled successfully but do not behave as expected. The process of testing and debugging applies to runtime errors only. Testing reveals these errors, and debugging repairs them. Configuring the Debugging EnvironmentWhen starting a program from Visual Studio .NET for debugging, you should ensure that the program is started in the Debug configuration. In addition to this, to enable debugging in the ASP.NET Web application or a Web service, make sure that the debug attribute of the <compilation> element in the web.config file is set to true.
<compilation
defaultLanguage="c#"
debug="true"/>
WARNING Applications Run Slowly in Debug Mode When debugging is enabled for an application, the compiler includes extra debugging information in the page, creating a large output file that executes slowly. Also, in ASP.NET Web applications and Web services, ensure that the Enable ASP.NET Debugging option is set to true. The Enable ASP.NET Debugging option is found in the Configuration Properties, Debugging option in the project's Property Pages dialog box. NOTE Debugging from Visual Studio .NET When you run an application from Visual Studio .NET, it automatically attaches a debugger to the process in which your application is running. In the case of ASP.NET Web applications and Web services, the debugger is also attached to the ASP.NET worker process (aspnet_wp.exe), if the Enable ASP.NET Debugging option is set to true in the project's Property Pages dialog box. Setting Breakpoints and Stepping Through Program ExecutionA common technique for debugging is to execute a program step by step. This systematic execution allows you to track the flow of logic, to ensure that the program is following the same paths of execution that you expect it to follow. If it does not, you can immediately identify the location of the problem. Using step-by-step execution of a program also gives you an opportunity to monitor the program's state before and after a statement is executed. For example, you can check the values of variables, the records in a database, and other changes in the environment. Visual Studio .NET provides tools to make these tasks convenient. The Debug menu provides three options for step-by-step execution of a program (see Figure). The keyboard shortcuts listed in Figure correspond to the default keyboard scheme of the Visual Studio .NET IDE. If you have personalized the keyboard scheme either through the Tools, Options, Environment, Keyboard menu, or through the Visual Studio .NET Start Page, you might have a different keyboard mapping. You can check out the keyboard mappings available for your customization through Visual Studio .NET's context-sensitive help. Breakpoints are markers in code that signal the debugger to pause execution. When the debugger pauses at a breakpoint, you can take your time to analyze variables, data records, and other settings in the environment to determine the state of the program. You can also choose to execute the program in step mode from this point onward. If you have placed a breakpoint in a button's Click event handler, the program pauses when you click the button and the execution reaches the breakpoint. You can then step through the execution for the rest of the event handler. When the execution of the event handler code finishes, the control is transferred back to the form. If you have another button on the form for which a breakpoint is not set in the event handler, then the program is no longer under step execution. You should mark breakpoints at all the places you would like execution to pause. Step-by-Step 9.7 shows you how to set breakpoints and perform step-by-step execution using Visual Studio .NET.
To set advanced options in a breakpoint, you can choose to create a new breakpoint by selecting New from the context menu of the code or from the toolbar in the Breakpoints window. The New Breakpoint dialog box (see Figure) has four tabs. You can use these tabs to set a breakpoint in a function, in a file, at an address in the object code, and when a data value (that is, the value of a variable) changes. 18. The New Breakpoint dialog box enables you to create a new breakpoint.
Clicking the Condition button opens the Breakpoint Condition dialog box, as shown in Figure. The Breakpoint Condition dialog box enables you to set a breakpoint based on the runtime value of an expression. 19. The Breakpoint Condition dialog box allows you to set a breakpoint that is based on the value of an expression at runtime.
Clicking the Hit Count button opens the Breakpoint Hit Count dialog box, as shown in Figure. This dialog box enables you to break the program execution only if the specified breakpoint has been hit a given number of times. This can be especially helpful if you have a breakpoint inside a lengthy loop and you want to step-execute the program only near the end of the loop. 20. The Breakpoint Hit Count dialog box enables you to break the program execution only if the specified breakpoint has been hit a specified number of times.
Analyzing Program State to Resolve ErrorsWhen you break the execution of a program, the program is at a particular state in its execution cycle. You can use various debugging tools to analyze the values of variables, the results of expressions, the path of execution, and so on, to help identify the cause of the error that you are debugging. Step-by-Step 9.8 demonstrates various Visual C# .NET debugging tools, such as the Watch, Autos, Locals, This, Immediate, Output, and Call Stack windows.
Debugging on ExceptionsYou can control the way the debugger behaves when it encounters a line of code that throws an exception. You can control this behavior through the Exceptions dialog box, which is shown in Figure and is invoked by selecting Debug, Exceptions. The Exceptions dialog box allows you to control the debugger's behavior for each type of exception defined on the system. In fact, if you have defined your own exceptions, you can also add them to this dialog box. 28. The Exceptions dialog box enables you to control the debugger's behavior for system and custom-defined exceptions.
There are two levels at which you can control the behavior of the debugger when it encounters exceptions:
NOTE Support for Cross-Language Debugging Visual Studio .NET supports debugging of projects that contain managed code written in several languages. The debugger can transparently step into and out of languages, making the debugging process smooth for you as a developer. Visual Studio .NET also extends this support to unmanaged code, but with minor limitations.
Debugging a Running ProcessUntil this point in the chapter, you have seen how to debug programs only by starting them from the Visual Studio .NET environment. However, Visual Studio .NET also allows you to debug processes that are running outside the Visual Studio .NET debugging environment. This feature can be quite helpful for debugging already-deployed applications. To access external processes from Visual Studio .NET, you need to invoke the Processes dialog box, shown in Figure. You can do this in two ways:
29. The Processes dialog box enables you to attach a debugger to a process that is under execution.
In the Processes dialog box, select the process that needs to be debugged in the Available Processes section and then click the Attach button to attach the process to the debugger. You can then open the source code files in Visual Studio .NET and place breakpoints in the code. Visual Studio .NET debugger breaks the execution of the process when the breakpoint is reached. You can invoke various debugging windows, such as the Watch, Locals, and Autos windows, to analyze variables and step through the program execution. Step-by-Step 9.9 demonstrates how to attach the debugger to a process that is being executed.
WARNING Terminating aspnet_wp.exe The ASP.NET worker process (aspnet_wp.exe) processes requests from all ASP.NET applications. If, after debugging, you choose to terminate the aspnet_wp.exe process, it will affect all Web applications running on the server. You need to be especially careful when selecting this option on a production/shared server. Don't Debug on a Production Server When you attach a debugger to the ASP.NET worker process aspnet_wp.exe, it freezes the execution of all other Web applications on that server. This might cause undesirable effects on a production server. However, to debug a deployed or running Web application, or a Web service, you need to attach the Visual Studio .NET debugger to the aspnet_wp.exe process running on the Web server. After this debugging setup is done, the Web programs can be debugged just like any other program. Debugging a Remote ProcessFor remote debugging to work, the Machine Debug Manager (mdm.exe) should be running on the remote computer. mdm.exe is a Windows service that provides remote debugging support. If the remote computer has never been set up for remote debugging, you take one of the following steps to do a one-time configuration on the remote machine:
NOTE Microsoft CLR Debugger (dbgclr.exe) The .NET Framework provides a tool called Microsoft CLR Debugger (dbgclr.exe). This tool is based on the Visual Studio .NET debugger and has most of the same features. This tool will be especially useful if you are not using Visual Studio .NET for developing your applications and still want all the powerful GUI-based debugging capabilities. You also must ensure that your user account is a member of the Debugger Users group on the remote machine. If you want to debug an ASP.NET worker process, you must also have administrative privileges (that is, you should be a member of the Administrators group) on the remote machine. If SQL Server is installed on the remote machine, the setup process just described also configures the machine for SQL Server stored procedures debugging, which is demonstrated at the end of this chapter, in Exercise 9.2. EXAM TIP Debugging a Remote Process The local computer and the remote computer must be members of a trusted domain for remote debugging to be possible. DCOM Error While Debugging Visual Studio .NET uses DCOM to enable remote debugging. If you get a DCOM configuration error while debugging, you didn't set up the remote machine to support remote debugging. To resolve the error make sure that you follow all the steps mentioned in this section. In addition to the already-mentioned one-time setup of the remote machine, you also need to configure the Visual Studio .NET project on your local machine. To do this you take the following steps:
After you have completed the required setup, the process of debugging a remote process is almost the same as the process of debugging an already running process. The only difference is that prior to selecting a running process from the Processes dialog box, you need to select the remote machine name from the Processes dialog box (refer to Figure). Debugging the Code in DLL FilesThe process of debugging a DLL file is similar to the process of debugging an EXE file. There is one difference though: The code in the DLL file cannot be directly invoked, so you need to have a calling program that calls various methods/components of the DLL files. You typically need to take the following steps to debug code in a DLL file:
In addition, if the code files are executing on a remote machine, you need to make sure that the remote machine is set up with remote debugging support, as explained in the previous section. Debugging Client-Side ScriptsVisual Studio .NET also allows you to debug client-side scripts. The process is similar to the process that I discussed earlier for Step-by-Step 9.9. However, you must note the following additional points for client-side scripting:
Debugging a Windows ServiceIn most aspects, debugging a Windows service is like debugging any other application. However, a Windows service runs within the context of the Service Control Manager. Therefore, to debug a Windows service, you must attach a debugger to the process in which the Windows service is running. If the Windows service is not already started, then you need to start the Windows service to perform debugging. WARNING Debugging Windows Service Processes When you attach a debugger to a Windows service, the service suspends its processing, but continues to be in the Started state. This may affect the execution of the Windows service. Therefore, you need to be especially careful when selecting this option on a production/shared server. Step-by-Step 9.10 shows you how to debug the OrderService service created in Step-by-Step 6.1 in Chapter 6, "Windows Services." If you haven't already created this service, you should create it now to follow Step-by-Step 9.10.
In Step-by-Step 9.10, you could have placed breakpoints in the OnStop(), OnPause(), OnContinue() methods. You could have then used the Services administrative tool to stop, pause, or continue the Windows service to debug the code in these methods. However, it is not possible to debug the OnStart() method (that starts the service) or the Main() method (that creates the instance of the service) by the process explained in Step-by-Step 9.10 because a Windows service needs to be already started before you can attach a debugger. To debug the constructor or the Main() method of a Windows service, you place a breakpoint in the Main() method and then run the application from Visual Studio .NET. Remember that this step just allows you to step into the Main() method but does not actually load the Windows service as the Service Control Manager does. To debug the code in the OnStart() method, you can call the OnStart() method from the Main() method, as shown in the following code:
static void Main()
{
System.ServiceProcess.ServiceBase[] ServicesToRun;
// Place a breakpoint in the following line to
// step into the OnStart() method
// This line needs to be removed after the debug
// process completes
(new OrderService()).OnStart(null);
ServicesToRun = new
System.ServiceProcess.ServiceBase[]
{ new OrderService() };
System.ServiceProcess.ServiceBase.Run(
ServicesToRun);
}
In these lines of code, a call to the OnStart() method is added just to debug the code in the OnStart() method. After the debug process, you should remove the call to the OnStart() method. NOTE Debugging the OnStart() Method When the Service Control Manager starts a Windows service by calling the OnStart() method, it waits just 30 seconds for the OnStart() method to return. If the method does not return in this time, the Service Control Manager shows an error that the service cannot be started. If a Windows service is executing on a remote machine, you need to make sure that the remote machine is set up with remote debugging support, as explained in the section "Debugging a Remote Process." Debugging a Serviced ComponentA serviced component is stored in a DLL file. The code in the serviced component cannot be directly invoked, so you need to have a client (calling) program that creates the serviced component object and calls various methods of the serviced component. Therefore to debug a serviced component, you need to take steps similar to those of debugging any DLL file. However, the debugging differs slightly depending on whether the serviced component application is a Library or Server application. If the serviced component is a Library application, then the serviced component runs in the client application's process. In this case, you can set breakpoints in the serviced component or the client application and run the client application in debug mode. When the breakpoint is reached, you can step into the serviced component's code. In case of an already running client application, you can set breakpoints in the serviced component or the client application and attach a debugger to the client application's process. On the other hand, if the serviced component is a Server application, then the serviced component runs in a separate process called dllhost.exe. Setting breakpoints in the client code and attaching a debugger to the client application debugs only the client application; it does not step into the code of the serviced component. In this case, to debug the serviced component you should place breakpoints in the serviced component code and attach a debugger to the dllhost.exe process in which the desired serviced component is running. If multiple COM+ server applications are running on a machine, then multiple dllhost.exe processes will be running on the machine. You can identify the unique process identifier (PID) of the dllhost.exe that is running your serviced component with the help of the Component Services administrative tool. Drill down to the COM+ Applications node and select View, Status View. You should now be able to view the PID for the dllhost.exe process that hosts the serviced component, as shown in Figure. 32. The Status View of the Component Services administrative tool gives detailed information on the status of the COM+ applications.
You can use the PID of the dllhost.exe process to attach a debugger to that process via the Processes dialog box, as shown in Figure. Figure. An Enterprise Services application that has Server activation mode runs in a separate process named dllhost.exe.
WARNING Setting the Computer Level Default Timeout When you increase the Transaction timeout value in the My Computer Properties dialog box, the setting affects all the transactions in the computer. Therefore, you should try to reset the default value as soon as possible, so that other applications using transactions are not affected in the computer. After attaching the process, you can place breakpoints to step into the code of the serviced component just like that of any other component. If you want to debug the client application as well, you should attach a debugger to the client application's process. So in this case, you attach debuggers to two processes: the serviced component's process and the client application's process. However, note that while debugging, the serviced components involving transactions may raise COMException errors indicating transaction timeout problems. The default computer-level setting for transactions timeout is 60 seconds. While debugging, you may want to increase the transaction timeout value. You can do so by overriding the default settings for your serviced component: Select the Override global transaction timeout value option in the Transactions tab of the serviced component's Properties dialog box, as shown in Figure. 34. You can set the timeout value for the serviced component's transactions in the serviced component's Properties dialog box.
Note the default value for the timeout if overridden is 0, which means the transactions will never time out. However, you should set a value greater than 0, so that there are no chances of distributed deadlocks. If you are debugging multiple serviced components that involve transactions, instead of increasing the timeout value for each serviced component, you can choose to increase the computer-level setting of the default timeout value. You can do this by changing the Transaction Timeout value in the Options tab of the My Computer Properties dialog box, as shown in Figure. You can open this dialog box by selecting Properties from the context menu of the My Computer node in the Component Services administrative tool. 35. You can set the timeout value for all the distributed transactions in a computer in the My Computer Properties dialog box.
If a serviced component is executing on a remote machine, you need to make sure that the remote machine is set up with remote debugging support, as explained in the section "Debugging a Remote Process." Debugging a .NET Remoting ObjectA .NET remoting object is stored in a DLL file, such as a serviced component. A .NET remoting object executes in the process of the remoting server application, without respect to its activation mode. Therefore, to debug a remoting object, you need to take the following steps:
After taking these steps, the Visual Studio .NET debugger breaks the execution when it reaches the breakpoint in the code. Attaching a debugger to the process in which the client application is running debugs only the client application and does not step into the code of the remoting object class definition. To debug both client and server applications, you can attach a debugger to both the applications and step seamlessly into the code of both the applications. If a remoting object is executing on a remote machine, you need to make sure that the remote machine is set up with remote debugging support, as explained in the section "Debugging a Remote Process." Debugging an XML Web ServiceDebugging XML Web services is similar to debugging Web applications. They also run in the ASP.NET worker process (aspnet_wp.exe). The only difference is that, you need to take care of setting breakpoints in the Web methods, after which you can debug Web services in any of the following ways:
You should also make sure that the Web service application is configured for debugging. Please refer to the "Configuring the Debugging Environment" section, discussed earlier in the chapter, for more details. Also, if the Web service is executing on a remote machine, you need to make sure that the remote machine is set up with remote debugging support, as explained in the section "Debugging a Remote Process." You can also use SOAP extensions of XML Web services for debugging. These SOAP extensions can be used to examine or modify the SOAP messages sent and received by the Web service or the client. Refer to the section "Creating and Using SOAP Extensions" in Chapter 5, "Advanced Web Services," for how to create and use SOAP extensions.
|
- Comment




















