T4 Tutorial: Debugging Code Generation Files


This post is a part of the series that introduces code generation with Text Templates (also known as T4 Templates) in Visual Studio using C# and Visual Basic; explains how to create reusable templates and combine them in complex code generators. In order to follow examples in this article, you need to have Visual Studio 2008 Standard Edition or higher, SQL Server 2005 or later, T4 Toolbox and T4 Editor installed on your computer.

Overview

As you remember from the previous article in this series, Runtime Errors are caused by exceptions thrown by code in the GeneratedTextTransformation class, which is compiled and executed by the code generation Engine.

Compilation and Runtime Errors

Although the Engine reports detailed stack dump for every exception thrown, troubleshooting non-trivial runtime errors may require using a debugger to step through the template code as it executes. Because template code is running inside of Visual Studio process itself, a second instance of Visual Studio is required to serve as a debugger for the first instance, which is running the template code.

Current support for debugging of code generation templates in Visual Studio is somewhat limited. It requires you to either use a manual breakpoint in the template code to trigger the just-in-time debugger or starting a debugging instance of Visual Studio in advance and attaching it to the instance that’s running the template.

Setup

Use Visual Studio to open CrudStoredProcedures.tt created in the first article of this series (you can download the source code using links at the end of this article). As you remember, it’s a code generation file that produces a DELETE stored procedure using table schema information retrieved from SQL server using SMO.

  • Simulate a runtime error by assigning null or Nothing to the server variable. This should trigger a run-time exception in the call to Database constructor.
  • Save the template file or select Run Custom Tool item from context menu in Solution Explorer to trigger template transformation.

Troubleshooting Runtime Errors

C#

Introducing ArgumentNullException in C# code

Visual Basic

Introducing ArgumentNullException in Visual Basic code

Runtime Error, Error List

    Just-In-Time Debugging

The quickest way to start debugging is by placing a breakpoint in the code of the template and triggering the just-in-time debugger. Note, if you are using Windows Vista or 2008 Server, this technique can hang Visual Studio. Please read the Just In Time Debugging on Windows Vista and 2008 Server section below first.

  • Make sure that debug parameter of the template directive is set to True.
  • Modify the template to call Debugger.Break method in the beginning of the code block.
C#

Setting just-in-time breakpoint in C# code

Visual Basic

Setting just-in-time breakpoint in Visual Basic code

  • Save the template file or select Run Custom Tool item from context menu in Solution Explorer to trigger template transformation.

Just-in-time debugging prompt

Debugger.Break method attempts to launch the Just-In-Time Debugger configured on your system.You should see a Visual Studio Just-In-Time Debugger dialog (shown above).

  • In Visual Studio Just-In-Time Debugger dialog, select New instance of Visual Studio 2008 in the list and click Yes.
C#

Stepping from just-in-time breakpoint in C# code

Visual Basic

Stepping from just-in-time breakpoint in Visual Basic code

This will launch a new instance of Visual Studio and attach it as a debugger to the first instance which is running your template. You should see the source code of your template automatically loaded in debugger and a green line pointing where the execution point currently is.

While in debugger, you can use all standard features, like stepping through code, and windows, like Watch, Call Stack, Immediate, etc.

  • Select Exceptions item from Debug menu in Visual Studio; turn on the option to break when exception is thrown and click OK.

Turning on Break-On-Exception option

  • Select Continue item from Debug menu in Visual Studio.

Exception details dialog

The template will continue to run until it encounters the exception. At that point, the Visual Studio debugger will pause it and display the dialog shown above. You can inspect the exception object by clicking View Detail link.

  • Select Continue item from Debug menu.
  • Close the debugging instance of Visual Studio.
  • Back in the original instance of Visual Studio, remove the call to Debugger.Break method from the template code.

Just-In-Time Debugging on Windows Vista and 2008 Server

By default on Windows Vista, the just-in-time debugger is configured to display a user-friendly dialog shown below. Although you can click the Debug the program button and start the debugger successfully, your original Visual Studio instance will hang in the end of the debugging session.

User-defined breakpoint dialog on Windows Vista

In order to avoid having to constantly kill the Visual Studio process after debugging, you will want to change Just-In-Time debugger configuration to work the same way it does on Windows XP and Windows Server 2003. This configuration is stored in registry as DbgJITDebugLaunchSetting value in HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework key. It’s default value on Windows Vista is 0×10. Change it to 0×2, which is the default value on Windows XP. After making this change, you should no longer see the User-Defined Breakpoint dialog and will be able to continue using Visual Studio after debugging.

Attaching Debugger Manually

Just-in-time debugging, described above, is the fastest and most precise way to set a breakpoint in template code and hit it in the debugger. However, it may not be appropriate if the code generation file you want to debug is read-only (such as when it is stored in source control repository or received from a third-party). In this situation, you can attach the debugger manually, which takes longer but doesn’t require you to modify the template code.

  • Start a second instance of Visual Studio and open the code generation file you need to debug - CrudStoredProcedures.tt in this example.
  • Select Attach to Process from the Debug menu in Visual Studio.

Attach to Process dialog

  • In the list of Available Processes, select devenv.exe and click the Attach button. This will attach the current instance of Visual Studio as a debugger for the first instance of Visual Studio running the template. Let’s call the first instance as simply Visual Studio and the second instance as Debugger.
  • Back in text editor of the Debugger, where you have the CrudStoredProcedures.tt file open, click on the left side of line 8 to sent a breakpoint.
C#

Setting breakpoint in C# code using attached debugger

Visual Basic

Setting breakpoint in Visual Basic code using attached debugger

Normally, the red breakpoint icon would appear next to the line you clicked. However, due to limitations in the current support for template debugging, Visual Studio displays the breakpoint icon in line 2 instead.

  • In the original Visual Studio instance, trigger template transformation by either saving the template or selecting Run Custom Tool from the context menu in Solution Explorer. This will trigger the breakpoint and you will see something like this in the Debugger.
C#

Stepping through C# code in attached debugger

Visual Basic

Stepping through Visual Basic code in attached debugger

You can use all debugging features as you would expect in regular .NET code with the exception of breakpoints. I have not found a way to place breakpoints in the template code precisely using the debugger and have to resort to manual breakpoints using Debugger.Break as described above.

  • Select Continue item from Debug menu.
  • Close the debugging instance of Visual Studio.
  • Back in the original instance of Visual Studio, restore the original initialization code for server variable.

Conclusion

Debugging is the most powerful technique in troubleshooting runtime errors that occur during code generation. Although current support for debugging of template code in Visual Studio is somewhat limited, you can debug templates effectively by either triggering Just-In-Time debugger with Debugger.Break from template code or by attaching a separate instance of Visual Studio as a debugger in advance.

In the next article of this series, we will talk about creating reusable code generation templates.

Download

Source code, C#
Source code, Visual Basic


Write a Comment

Take a moment to comment and tell us what you think. Some basic HTML is allowed for formatting.

Reader Comments

Hey Oleg

Great Site… Really good. I’m Loving T4 largely down to your wonderful source of information..

I’m reading your page on Debugging a T4 script. I’m using VS2008 Pro and Vista Ultimate 64bit Edition… Unfortunately it seems that even after following your advise on editing the registry to allow debugging… I am still experiencing a crash that takes out VS instead of launching a new version for debugging.

Any additional ideas?

ok, as seems to be the way of the web, as soon as I posted my comment…I have found the solution. It seems that the 64bit edition requires that the registry switch is placed in a different location for 32bit apps. Therefore the “Microsoft” part of the registry path mentioned in fact sits under and additional ‘Wow6432Node’ Folder in my case. This sorted … Everything works :) Thanks again Oleg.

[…] Oleg states here, if you need to analyze assemblies during code generation, you should use fxcop […]

Hey Oleg,

thanks for the info. I tried to debug some Run time error. Unfortunately the Break command seems not to be picked up. It has no effect :( I have set the T4 attribute to debug = true. I’m running VS2008 with SP1.

Any idea?

Alex.

Alex, what did you refer to when you said “Break command”? Are you using Debugger.Break(); statement?

Awesome post. Thanks.

[…] previously a process for debugging a misbehaving template existed, it was not intuitive and somewhat of a hassle (requiring multiple instances of Visual Studio). Our […]

[…] a slightly-modified version of the ADO.NET POCO Entity Generator template using the directions Oleg Sych published a few years back. I modified the DbgJITDebugLaunchSetting key as […]