Get Visual Studio to run a T4 Template on every build

70,072

Solution 1

I used JoelFan's answer to come up w/ this. I like it better because you don't have to remember to modify the pre-build event every time you add a new .tt file to the project.

  • add TextTransform.exe to your %PATH%
  • created a batch file named transform_all.bat (see below)
  • create a pre-build event "transform_all ..\.."

transform_all.bat

@echo off
SETLOCAL ENABLEDELAYEDEXPANSION

:: set the working dir (default to current dir)
set wdir=%cd%
if not (%1)==() set wdir=%1

:: set the file extension (default to vb)
set extension=vb
if not (%2)==() set extension=%2

echo executing transform_all from %wdir%
:: create a list of all the T4 templates in the working dir
dir %wdir%\*.tt /b /s > t4list.txt

echo the following T4 templates will be transformed:
type t4list.txt

:: transform all the templates
for /f %%d in (t4list.txt) do (
set file_name=%%d
set file_name=!file_name:~0,-3!.%extension%
echo:  \--^> !file_name!    
TextTransform.exe -out !file_name! %%d
)

echo transformation complete

Solution 2

I agree with GarethJ - in VS2010 it is much easier to regenerate tt templates on each build. Oleg Sych's blog describes how to do it. In short:

  1. Install Visual Studio SDK
  2. Install Visual Studio 2010 Modeling and Visualization SDK
  3. Open in text editor project file and add to the end of file but before </Project>

That's it. Open your project. On each build all *.tt templates will be reprocessed

<!-- This line could already present in file. If it is so just skip it  -->
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- process *.tt templates on each build  -->
<PropertyGroup>
    <TransformOnBuild>true</TransformOnBuild>
</PropertyGroup>
<Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\TextTemplating\v10.0\Microsoft.TextTemplating.targets" />

Solution 3

There is a great NuGet package that does just this:

PM> Install-Package Clarius.TransformOnBuild

Details about the package can be found here and the GitHub repo is here.

Solution 4

I used MarkGr's answer and developed this solution. First, create a batch file called RunTemplate.bat in a separate tools folder above the main solution folder. The batch file just has the line:

"%CommonProgramFiles%\Microsoft Shared\TextTemplating\1.2\texttransform.exe" -out %1.cs -P %2 -P "%ProgramFiles%\Reference Assemblies\Microsoft\Framework\v3.5" %1.tt

This batch file takes 2 parameters... %1 is the path to the .tt file without the .tt extension. %2 is the path to any DLLs referred to by Assembly directives in the template.

Next, go into the Project Properties of the project containing the T4 template. Go into Build Events and add the following Pre-build event command line:

$(SolutionDir)..\..\tools\RunTemplate.bat $(ProjectDir)MyTemplate $(OutDir)

replacing MyTemplate with filename of your .tt file (i.e. MyTemplate.tt) without the .tt extension. This will have the result of expanding the template to produce MyTemplate.cs before building the project. Then the actual build will compile MyTemplate.cs

Solution 5

Recently found this great VS plugin, Chirpy.

Not only does it generate your T4 on a build, but it allows T4-based approach to minification of javascript, CSS, and even lets you use LESS syntax for your CSS!

Share:
70,072

Related videos on Youtube

user1601201
Author by

user1601201

Updated on March 19, 2022

Comments

  • user1601201
    user1601201 about 2 years

    How do I get a T4 template to generate its output on every build? As it is now, it only regenerates it when I make a change to the template.

    I have found other questions similar to this:

    T4 transformation and build order in Visual Studio (unanswered)

    How to get t4 files to build in visual studio? (answers are not detailed enough [while still being plenty complicated] and don't even make total sense)

    There has got to be a simpler way to do this!

    • Pavel Minaev
      Pavel Minaev over 14 years
      While I would personally be quite interested to hear an answer to this, what is your particular scenario? Normally the output of the template should be a function of the input only, so generating on change is fine.
    • user1601201
      user1601201 over 14 years
      My template uses reflection to examine other assemblies, which may have changed since the last build.
    • user1601201
      user1601201 over 14 years
    • Scott Solmer
      Scott Solmer about 4 years
      My template serves one purpose, record the build date time.
    • Karel Frajták
      Karel Frajták about 3 years
  • MarkGr
    MarkGr over 14 years
    Oh, although you can do stuff like "devenv /Command TextTransformation.TransformAllTemplates /Command File.Exit MySolution.sln" on 2010 it tends to break on build servers occasionally. Your best bet is to write a MSBuild task with a custom host.
  • MarkGr
    MarkGr over 14 years
    For desktop builds, just make a macro that does a TransformAllTemplates, and then a build.
  • user1601201
    user1601201 over 14 years
    although I still have the problem: stackoverflow.com/questions/1669893/…
  • Ewald Hofman
    Ewald Hofman over 13 years
    Don't forget the quotes around $(SolutionDir)..\..\tools\RunTemplate.bat
  • ChocoMartin
    ChocoMartin about 13 years
    Nice solution. I preferred putting the full path to TextTransform.exe ("%CommonProgramFiles%\Microsoft Shared\TextTemplating\1.2\texttransform.exe") in the batch file, rather than adding it to %PATH%
  • PhilChuang
    PhilChuang almost 13 years
    Here's a link to Oleg Sych's blog post: olegsych.com/2010/04/understanding-t4-msbuild-integration
  • grimus
    grimus almost 13 years
    This is a very nice solution. However is there a way to get this to work without requiring the install of the SDKs? I've been trying to get it to work by copying out the .targets files and related assemblies, but without success.
  • Cheburek
    Cheburek almost 13 years
    I also do use Chirpy (see below in @Mark post) and on official site nothing is written about SDK dependency. So you should try it. Hope this help
  • Mir
    Mir over 12 years
    Chirpy appears to work without having to download any SDKs... however, you still have to download and configure Chirpy. I'm still trying to discover a solution that works on a default install of VS2010, and will be available via the source repository so that developers only need to check out the repo for it to work. All these other solutions require way too much per-developer attention.
  • Durden81
    Durden81 about 12 years
    A better variable would be %COMMONPROGRAMFILES(x86)% instead of %COMMONPROGRAMFILES% as it would also work on a 64bit system.
  • Andrea
    Andrea about 12 years
    I got "Running transformation: System.ArgumentNullException: Value cannot be null. Parameter name: Could not obtain DTE from host" and I cannot find solution..could you help me?
  • Evan Nagle
    Evan Nagle about 12 years
    What about with VS11, and how can you support both VS2010 and VS11 using this technique?
  • Rusted
    Rusted almost 12 years
    If you build your projects using x64 version of MSBuild - you will get this error: 'MSB4019: The imported project "C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\TextTemplating\v10.0\Mi‌​crosoft.TextTemplati‌​ng.targets" was not found.' error. Workaround - replace $(MSBuildExtensionsPath) variable by $(MSBuildExtensionsPath32) in a project file.
  • northben
    northben about 11 years
    So the full path will be %COMMONPROGRAMFILES(x86)%\microsoft shared\TextTemplating\11.0\TextTransform.exe. Wrap it in double quotes.
  • northben
    northben about 11 years
    You can filter your text transforms like this: dir %wdir%\*.tt /b /s | findstr /vi obj > t4list.txt. This excludes *.tt files found in my "obj" directory.
  • northben
    northben about 11 years
    @Andrea, we are both having this issue. It's because you're referencing Visual Studio environment variables in your transform file, but the transform is now not running in Visual Studio. I'm looking for a workaround myself...
  • piers7
    piers7 almost 11 years
    Just to clarify, %COMMONPROGRAMFILES(x86)% only exists on 64 bit machines (last I checked, anyways). Which is a pain. If you want a script to target a 32 bit binary, and 'just work' on either 64 bit or 32 bit machines you'll have to fiddle around a bit
  • Giulio Vian
    Giulio Vian almost 11 years
    @grimus you can just copy the needed files as explained at msdn.microsoft.com/en-us/library/ee847423.aspx#buildserver.
  • Giulio Vian
    Giulio Vian almost 11 years
    Moreover, you don't need to patch the .csproj files. From the command line invoke something like msbuild mySolution.sln /p:CustomAfterMicrosoftCommonTargets="C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v11.0\TextTemplating\Mi‌​crosoft.TextTemplati‌​ng.targets" /p:TransformOnBuild=true /p:TransformOutOfDateOnly=false
  • Alex Essilfie
    Alex Essilfie over 10 years
    @piers7: I updated the code to automatically detect the 'bitness' of the OS that is running the script. I have also included northben's comment to skip the obj directory and implemented Adam Nofsinger's preference on not modifying the %PATH% environment variable.
  • Seth Reno
    Seth Reno over 10 years
    @Alex - I appreciate the effort but I rolled your edits back because you pretty much completely re-wrote the script. I think it would make more sense if you posted your script as a separate answer.
  • Peter Taylor
    Peter Taylor about 10 years
    @SprintStar, if you have VS 2012 there's probably a better way of doing it. Other answers talk about better ways already existing for VS 2010.
  • yoel halb
    yoel halb almost 10 years
    I am unable to find this option on the right click menu, however according to the MSDN it is possible to do it by editing the project file in VS 2012 and 2013, see msdn.microsoft.com/en-us/library/ee847423.aspx or msdn.microsoft.com/en-us/library/vstudio/ee847423.aspx for details
  • Arkadiusz Kałkus
    Arkadiusz Kałkus over 9 years
    Nice but transforming all could be dangerous if T4MVC is not only tt in the project and we don't want to run all...
  • Tewr
    Tewr over 9 years
    The script breaks if the full path contains spaces. This is fixed in @Alex version by using "delims=" and wrapping the final arguments to texttransform with quotes
  • Matt DiTrolio
    Matt DiTrolio almost 9 years
    This appears to be an option that comes with tangible T4 tools only, not default in Visual Studio.
  • Ryan Gates
    Ryan Gates almost 9 years
    This is the best method, because I don't have to install anything.
  • Pompair
    Pompair over 8 years
    Yeah this is only in the pro version of T4 Toolbox.
  • Zack
    Zack over 8 years
    I don't have TextTemplating in the v11.0 folder. Where do you get that from?
  • Michael Lewis
    Michael Lewis over 8 years
    I'm trying to use this approach, but I keep getting an error, with '\Common was unexpected at this time.' in my output. It happens right at this line: for /f "delims=" %%d in (t4list.txt) do... Any idea what I'm missing?
  • Alex Essilfie
    Alex Essilfie over 8 years
    @MichaelLewis: I have gone through the batch file several times without spotting what could be causing the error. Kindly try the method proposed by Seth Reno to see if it generates the same error. In the mean time, can you please post your t4list.txt file to PasteBin so I try to see if your error is coming from there?
  • Michael Lewis
    Michael Lewis over 8 years
    I tried Seth's approach with the same issue ('\Common was unexpected at this time'). I can't post the t4list.txt file due to corporate restrictions, but it consists of one line, and \Common doesn't appear in the path.
  • Alex Essilfie
    Alex Essilfie over 8 years
    @MichaelLewis: Unfortunately, if your error occurs at for /f "delims=" %%d in (t4list.txt) do ( and corporate restrictions prevent you from posting your t4list.txt file, then I am afraid there is not much I can do to help you. I had really wanted to help solve this but it looks like it's going to be impossible since I have no data to proceed. Good luck in fixing the issue and kindly remember to post your solution when you are successful.
  • komodosp
    komodosp about 8 years
    Saw there was no 1.2 but there was a 12.0 so changed it to that but got this error: System.Exception: T4MVC can only execute through the Visual Studio host
  • Frank van Wijk
    Frank van Wijk about 8 years
    Please add the solution itself to your answer to provide more context. Links are no solutions to the question and may be dead when other users come back to this question later.
  • Ohad Schneider
    Ohad Schneider over 7 years
    Another nice thing about it is that it works with command-line MSBuild builds as well - not just Visual Studio (since it uses TextTransform.exe). Looking at the GitHub repo it actually looks like he has code that supports content build actions and much more - but sadly no new release have been made since February 2015 (before said fixes were implemented).
  • pistol-pete
    pistol-pete over 7 years
    Just had to update the folder path to use 14.0 instead of 1.2 and good to go.
  • Gyromite
    Gyromite over 7 years
    Agreed! Configurable, and works with VS 2015. It even supports use of the EnvDTE assembly (for getting build configuration), which not all methods do. The only downside is that all team members have to install the extension.
  • Emond
    Emond over 7 years
    There is an 'unofficial' fork: nuget.org/packages/Clarius.TransformOnBuild-unofficial that supports content build actions
  • Gh61
    Gh61 over 7 years
    It's nice extension but it's running TextTransform.exe in commandLine mode, so hostspecific="true" funcions will not work
  • Jez
    Jez almost 7 years
    IMHO having to provide the path to TextTransform.exe sucks. You can already right-click "Run Custom Tool" in Visual Studio, so it already has the tool's path. Why do I have to go through the work of providing it again when I'm building from a Visual Studio context?
  • Jez
    Jez almost 7 years
    Installing a whole SDK just to generate text templates that you can do by default in Visual Studio is utterly ridiculous.
  • Jenish Rabadiya
    Jenish Rabadiya almost 7 years
    It generates .txt file while I wanted to generate .cs file. What should I do?
  • Peter van Kekem
    Peter van Kekem almost 7 years
    @JenishRabadiya Add this line to the top of the template: <#@ template language="C#" #>
  • Mingwei Samuel
    Mingwei Samuel over 6 years
    It appears the package has been updated to support hostspecific="true" and other issues (8 days ago)
  • androbin
    androbin over 5 years
    Content build action is working now with the latest version.
  • Nelson Rodriguez
    Nelson Rodriguez over 5 years
    This was the best solution in my opinion (just changing 14.0 as mentioned above)
  • el_technic0
    el_technic0 about 5 years
    On my machine the TextTransform tool is very slow, like 6 seconds of wait added to every build. This is unacceptable for me.
  • Andrey K.
    Andrey K. almost 5 years
    Is it possible to do the same when tt contains (this.Host as IServiceProvider).GetService(typeof(EnvDTE.DTE)) as EnvDTE.DTE;? Unfortunatelly, I get null reference exception, when I run tt from not inside visual studio.
  • Andrey K.
    Andrey K. almost 5 years
    Is it possible to do the same when tt contains (this.Host as IServiceProvider).GetService(typeof(EnvDTE.DTE)) as EnvDTE.DTE;? Unfortunatelly, I get null reference exception, when I run tt from not inside visual studio.
  • Constantine Ketskalo
    Constantine Ketskalo almost 4 years
    Probably this package had some problems at first but now this is the best solution. Looks like stackoverflow needs to handle somehow answers, that are outdated and those answers, that become the best over time after updates. )
  • sw1337
    sw1337 over 3 years
    I really like your approach but I can't run your project on .Net Core 3.0+. Apparently DotNetCliToolReference was retired and I'm not sure how to run your solution with whatever the new way is. See github.com/dotnet/announcements/issues/107
  • Konard
    Konard over 3 years
    @MelLeet I`ll try to look into it in near future, if you like you can create an issue in my repository about that.
  • Keith Stein
    Keith Stein over 2 years
    Currently, to get this working with VS 2022, I needed to add the following to my project file (inside a pair of PropertyGroup tags): <TextTransformPath>$(VsInstallRoot)\Common7\IDE\TextTransfor‌​m.exe</TextTransform‌​Path>
  • Conure
    Conure about 2 years
    If you have spaces in your solution path, you will need to put quotes around $(SolutionPath) in the above. Otherwise, I like this solution since it's just a build event and has no other dependencies. The drawback being that you have to specify every file you want transformed ahead of time. Thank you!
  • daniol
    daniol about 2 years
    You can use "$(DevEnvDir)TextTransform.exe" instead of hardcoding the TextTransform path
  • Moby Disk
    Moby Disk about 2 years
    @PhilChuang: Wayback machine link to Oleg Sych's blog post: web.archive.org/web/20110816220543/http://olegsych.com/2010/‌​04/…
  • Moby Disk
    Moby Disk about 2 years
    Thanks for posting this update. I kept hoping that eventually msbuild would support t4 templates out-of-the-box.