分类：.NET

This post is a part of the series that introduces code generation with Text Templates (also known as T4Templates) 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 Editorinstalled 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.

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#

Visual Basic

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.

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

C#

Visual Basic

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.

Select Continue item from Debug menu in Visual Studio.

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.

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.

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#

Visual Basic

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#

Visual Basic

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.

What’s the story? Well, T4 is a code generator built right into Visual Studio. To be clear, you HAVE THIS NOW on your system…go play. Now’s the time to introduce code generation to your company. If you’re doing something twice or more, manually, in your company, generate it.

However, it’s not deep-deep built in, because there’s no item templates in File | New Item and there’s no intellisense or syntax highlighting.

You don’t need this, but if you want really get the most out of T4, first, head over to Clarius Consulting and get their “T4 Editor Community Edition.” That’ll get you some basic coloring. They have a pay version that gets you more if you want.

Now, go into Visual Studio and make a Console App (or any app) and add a Text File, but name it something with a .tt extension. You’ll get a warning since it’s a generator, that someone could generate evil. Click OK if you are cool with potential evil. ;)

Now, look in Solution Explorer at the .tt file. If you’re using C#, you’ll have a sub .cs file, or if you’re using VB, a sub .vb file. That’s the file that will hold the result of the generation. This is the same visual metaphor used to the express the template/generated file relationship with .designer files you’ve seen elsewhere in Visual Studio.

If you look in the Properties for the .tt file, you’ll see it’s using a CustomTool listed as the “TextTemplatingFileGenerator.” This custom tool extensibility point is how things like XSD and WSDL code generators hook in to generate their artifacts.

T4 can generate any kind of text file, not just code. Whatever you like. You can use it in your projects, as above, or you can call T4 from the command-line.

Notice that I’ve named the .tt file the same as the .dbml, so Damian’s code can find it. I also continue to let original LINQ to SQL generate it’s .designer.cs file, but make that file’s Build Action “None” so it’s not ever compiled. That effectively puts Damian’s code in charge.

Here’s a screenshot showing a bit of Damian’s T4 template using the syntax highlighting from the Clairus T4 Visual Studio free download. If I’d pay them, I’d get intellisense and syntax highlighting inside the code blocks also. It looks like a lot like ASP.NET Web Forms, or Velocity, or any templating language really. The code blocks are where your logic is and outside the codeblocks is the template for whatever you want to generate. Notice how Damien gets input and sets output. You have full control, you can read files off the file system, from with your project, etc. He sets the output extension also. I like to use .g.cs or .g.vb, myself. In this example his generated file is Chinook.generated.cs.

I particularly like Damien’s example because he’s swapping out parts of LINQ to SQL that he didn’t like (the generated code) while keeping the part he did (the general mode, the designer, the dbml file.) If you don’t like something, fix it.

Plus, it all works in Visual Studio without installing anything.

If you’re doing Code Gen, or thinking about it, check out T4 as it’s a great place to start. Also, search my blog for “Code Generation” as I was livign and breathing it with CodeSmith for the many years I worked atCorillian. Have fun!

Function 2: Object.defineProperty

●value: use this to set the value of a property. Defaults to undefined.

●writable: use this boolean to define whether this is a read-only variable. If it’s writable, it’s true. Defaults to false.

●configurable: use this boolean to define whether the type (value vs. method) of this property can be changed, or whether the property can be deleted. If it’s configurable, it’s true. Defaults to false.

●enumerable: use this boolean to define whether this property is included when the properties of the object are enumerated (a for-in loop or the keys method). Defaults to false.

●get: use this to define a custom getter method. Defaults to undefined.

●set: use this to define a custom setter method. Defaults to undefined.