Get Visual Studio to run a T4 Template on every build
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:
- Install Visual Studio SDK
- Install Visual Studio 2010 Modeling and Visualization SDK
- 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!
Related videos on Youtube
user1601201
Updated on March 19, 2022Comments
-
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 over 14 yearsWhile 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 over 14 yearsMy template uses reflection to examine other assemblies, which may have changed since the last build.
-
user1601201 over 14 yearsWhat about this idea: stackoverflow.com/questions/1649649/…
-
Scott Solmer about 4 yearsMy template serves one purpose, record the build date time.
-
Karel Frajták about 3 years
-
-
MarkGr over 14 yearsOh, 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 over 14 yearsFor desktop builds, just make a macro that does a TransformAllTemplates, and then a build.
-
user1601201 over 14 yearsalthough I still have the problem: stackoverflow.com/questions/1669893/…
-
Ewald Hofman over 13 yearsDon't forget the quotes around $(SolutionDir)..\..\tools\RunTemplate.bat
-
ChocoMartin about 13 yearsNice 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 almost 13 yearsHere's a link to Oleg Sych's blog post: olegsych.com/2010/04/understanding-t4-msbuild-integration
-
grimus almost 13 yearsThis 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 almost 13 yearsI 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 over 12 yearsChirpy 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 about 12 yearsA better variable would be %COMMONPROGRAMFILES(x86)% instead of %COMMONPROGRAMFILES% as it would also work on a 64bit system.
-
Andrea about 12 yearsI 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 about 12 yearsWhat about with VS11, and how can you support both VS2010 and VS11 using this technique?
-
Rusted almost 12 yearsIf 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\Microsoft.TextTemplating.targets" was not found.' error. Workaround - replace $(MSBuildExtensionsPath) variable by $(MSBuildExtensionsPath32) in a project file.
-
northben about 11 yearsSo the full path will be
%COMMONPROGRAMFILES(x86)%\microsoft shared\TextTemplating\11.0\TextTransform.exe
. Wrap it in double quotes. -
northben about 11 yearsYou 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 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 almost 11 yearsJust 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 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 almost 11 yearsMoreover, 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\Microsoft.TextTemplating.targets" /p:TransformOnBuild=true /p:TransformOutOfDateOnly=false
-
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 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 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 almost 10 yearsI 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 over 9 yearsNice but transforming all could be dangerous if T4MVC is not only tt in the project and we don't want to run all...
-
Tewr over 9 yearsThe 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 almost 9 yearsThis appears to be an option that comes with tangible T4 tools only, not default in Visual Studio.
-
Ryan Gates almost 9 yearsThis is the best method, because I don't have to install anything.
-
Pompair over 8 yearsYeah this is only in the pro version of T4 Toolbox.
-
Zack over 8 yearsI don't have TextTemplating in the v11.0 folder. Where do you get that from?
-
Michael Lewis over 8 yearsI'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 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 over 8 yearsI 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 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 yourt4list.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 about 8 yearsSaw 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 about 8 yearsPlease 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 over 7 yearsAnother 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 supportscontent
build actions and much more - but sadly no new release have been made since February 2015 (before said fixes were implemented). -
pistol-pete over 7 yearsJust had to update the folder path to use 14.0 instead of 1.2 and good to go.
-
Gyromite over 7 yearsAgreed! 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 over 7 yearsThere is an 'unofficial' fork: nuget.org/packages/Clarius.TransformOnBuild-unofficial that supports
content
build actions -
Gh61 over 7 yearsIt's nice extension but it's running TextTransform.exe in commandLine mode, so hostspecific="true" funcions will not work
-
Jez almost 7 yearsIMHO 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 almost 7 yearsInstalling a whole SDK just to generate text templates that you can do by default in Visual Studio is utterly ridiculous.
-
Jenish Rabadiya almost 7 yearsIt generates .txt file while I wanted to generate .cs file. What should I do?
-
Peter van Kekem almost 7 years@JenishRabadiya Add this line to the top of the template:
<#@ template language="C#" #>
-
Mingwei Samuel over 6 yearsIt appears the package has been updated to support hostspecific="true" and other issues (8 days ago)
-
androbin over 5 yearsContent build action is working now with the latest version.
-
Nelson Rodriguez over 5 yearsThis was the best solution in my opinion (just changing 14.0 as mentioned above)
-
el_technic0 about 5 yearsOn my machine the
TextTransform
tool is very slow, like 6 seconds of wait added to every build. This is unacceptable for me. -
Andrey K. almost 5 yearsIs 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. almost 5 yearsIs 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 almost 4 yearsProbably 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 over 3 yearsI 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 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 over 2 yearsCurrently, 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\TextTransform.exe</TextTransformPath>
-
Conure about 2 yearsIf 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 about 2 yearsYou can use "$(DevEnvDir)TextTransform.exe" instead of hardcoding the TextTransform path
-
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 about 2 yearsThanks for posting this update. I kept hoping that eventually msbuild would support t4 templates out-of-the-box.