获取Visual Studio在每个版本上运行T4模板

我如何获得一个T4模板来生成每个构建的输出? 就像现在一样,当我对模板进行更改时,它只会重新生成它。

我发现了类似这样的其他问题:

在Visual Studio中T4转换和构建顺序 (未答复)

如何让t4文件在Visual Studio中生成? (答案不够详细[虽然还很复杂],甚至没有总体意义)

必须有一个更简单的方法来做到这一点!

我用JoelFan的回答来提出这个问题。 我更喜欢它,因为每次将新的.tt文件添加到项目时,都不必记住修改预生成事件。

  • 将TextTransform.exe添加到您的%PATH%
  • 创建了一个名为transform_all.bat的批处理文件(见下文)
  • 创建一个预生成事件“ 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 

我同意GarethJ – 在VS2010中,在每个版本上重新生成tt模板要容易得多。 奥列格Sych的博客介绍了如何做到这一点。 简而言之:

  1. 安装Visual Studio SDK
  2. 安装Visual Studio 2010建模和可视化SDK
  3. 在文本编辑器项目文件中打开,并添加到文件的末尾,但在</Project>之前

而已。 打开你的项目。 在每个版本上,所有* .tt模板将被重新处理

 <!-- 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" /> 

我使用了MarkGr的答案并开发了这个解决方案。 首先,在主解决方案文件夹上方的独立工具文件夹中创建一个名为RunTemplate.bat的批处理文件。 批处理文件只有一行:

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

此批处理文件需要2个参数… %1是没有.tt扩展名的.tt文件的路径。 %2是由模板中的Assembly指令引用的任何DLL的路径。

接下来,进入包含T4模板的项目的项目属性。 进入构建事件并添加以下预构建事件命令行

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

用.tt文件的文件名替换MyTemplate (即MyTemplate.tt),不带.tt扩展名。 这将会在生成项目之前扩展模板以生成MyTemplate.cs。 然后,实际构建将编译MyTemplate.cs

有一个很棒的NuGet包,可以做到这一点:

 PM> Install-Package Clarius.TransformOnBuild 

关于这个包的细节可以在这里找到

最近发现这个伟大的VS插件, Chirpy 。

它不仅可以在构建中生成T4,还可以使用基于T4的方法缩小JavaScript,CSS,甚至可以让CSS使用LESS语法!

预构建可以简化为一行:

 forfiles /p "$(ProjectDir)." /m "*.tt" /s /c "cmd /c echo Transforming @path && \"%CommonProgramFiles(x86)%\Microsoft Shared\TextTemplating\1.2\TextTransform.exe\" @file" 

这将转换项目中的所有.tt文件,并将它们列出到构建输出中。

如果你不想要构建输出,那么你必须解决一些“有趣的行为” :

 forfiles /p "$(ProjectDir)." /m "*.tt" /s /c "cmd /c @\"%CommonProgramFiles(x86)%\Microsoft Shared\TextTemplating\1.2\TextTransform.exe\" @file" 

当然,如果你愿意的话,你可以把它拖到一个批处理文件中,通过它你可以传递项目目录的路径。

注意路径可能需要一些调整。 上面的路径是VS 2008在我的机器上安装它的地方; 但是您可能会发现TextTemplatingTextTransform.exe之间的版本号是不同的。

可能最简单的方法是安装名为AutoT4的Visual Studio扩展。

它自动运行所有T4模板。

签出C:\ Program Files文件(x86)\ Common Files \ Microsoft Shared \ TextTemplating那里有一个命令行转换exe。 或者用自定义主机编写一个MSBuild任务,然后自己进行转换。

在Seth Reno和JoelFan的回答中,我提出了这个问题。 有了这个解决方案,不需要记住在每次向项目添加一个新的.tt文件时修改预生成事件。

实施程序

  • 创建一个名为transform_all.bat的批处理文件(见下文)
  • 使用.tt构建每个项目的预生成事件transform_all.bat "$(ProjectDir)" $(ProjectExt)

transform_all.bat

 @echo off SETLOCAL ENABLEDELAYEDEXPANSION :: set the correct path to the the app if not defined ProgramFiles(x86). ( echo 32-bit OS detected set ttPath=%CommonProgramFiles%\Microsoft Shared\TextTemplating\1.2\ ) else ( echo 64-bit OS detected set ttPath=%CommonProgramFiles(x86)%\Microsoft Shared\TextTemplating\1.2\ ) :: set the working dir (default to current dir) if not (%1)==() pushd %~dp1 :: set the file extension (default to vb) set ext=%2 if /i %ext:~1%==vbproj ( set ext=vb ) else if /i %ext:~1%==csproj ( set ext=cs ) else if /i [%ext%]==[] ( set ext=vb ) :: create a list of all the T4 templates in the working dir echo Running TextTransform from %cd% dir *.tt /b /s | findstr /vi obj > t4list.txt :: transform all the templates set blank=. for /f "delims=" %%d in (t4list.txt) do ( set file_name=%%d set file_name=!file_name:~0,-3!.%ext% echo: \--^> !!file_name:%cd%=%blank%! "%ttPath%TextTransform.exe" -out "!file_name!" "%%d" ) :: delete T4 list and return to previous directory del t4list.txt popd echo T4 transformation complete 

笔记

  1. 文本转换假设T4模板中的代码与您的项目类型是相同的语言。 如果这种情况不适用于您,那么您将不得不将$(ProjectExt)参数替换为您想要代码生成的文件的扩展名。

  2. .TT文件必须在项目目录中,否则它们将不会生成。 您可以通过指定不同的路径作为第一个参数( 用包含TT文件的路径替换"$(ProjectDir)"来在工程目录之外生成TT文件。

  3. 还请记住将正确的路径设置为transform_all.bat批处理文件。
    例如,我把它放在我的解决方案目录中,所以预生成事件如下"$(SolutionDir)transform_all.bat" "$(ProjectDir)" $(ProjectExt)

如果您使用Visual Studio 2010,则可以使用Visual Studio Modeling and Visualization SDK: http : //code.msdn.microsoft.com/vsvmsdk

这包含构建时执行T4模板的msbuild任务。

看看奥列格的博客更多的解释: http : //www.olegsych.com/2010/04/understanding-t4-msbuild-integration

嘿,我的脚本也可以解析输出扩展

 for /r %1 %%f in (*.tt) do ( for /f "tokens=3,4 delims==, " %%a in (%%f) do ( if %%~a==extension "%CommonProgramFiles%\Microsoft Shared\TextTemplating\1.2\texttransform.exe" -out %%~pnf.%%~b -P %%~pf -P "%ProgramFiles%\Reference Assemblies\Microsoft\Framework\v3.5" %%f ) ) echo Exit Code = %ERRORLEVEL% 

只需创建transform_all.bat $(SolutionDir)预生成事件, transform_all.bat $(SolutionDir)所有* .tt文件将自动转换。

Dynamo.AutoTT将会做你所需要的。 您可以将其配置为通过正则表达式观看文件或在构建时生成。 它也允许你指定你想要触发哪个T4模板。

你可以从这里下载: https : //github.com/MartinF/Dynamo.AutoTT

只需构建它,将dll和AddIn文件复制到

C:\ Users \ Documents \ Visual Studio 2012 \ Addins \

并离开你去。

如果你想在VS2012中使用它,你将需要修改一个Dynamo.AutoTT.AddIn文件,并在AddIn文件中设置版本为11.0;

另一篇关于此的好文章: 构建过程中的代码生成

2012建模与可视化SDK下载链接:

https://www.microsoft.com/en-us/download/details.aspx?id=30680

请参阅mhutch的回答https://stackoverflow.com/a/1395377/9587

恕我直言,这是最好的构建服务器和开发环境友好的选择。

这是我的解决方案 – 类似于接受的答案。 我们的源代码管理有问题。 目标.cs文件是只读的,T4失败。 以下是在临时文件夹中运行T4的代码,比较目标文件,只有在相同更改的情况下才复制它。 它不能解决与read.only文件的问题,但至少不会经常发生:

Transform.bat

 ECHO Transforming T4 templates SET CurrentDirBackup=%CD% CD %1 ECHO %1 FOR /r %%f IN (*.tt) DO call :Transform %%f CD %CurrentDirBackup% ECHO T4 templates transformed goto End :Transform set ttFile=%1 set csFile=%1 ECHO Transforming %ttFile%: SET csFile=%ttFile:~0,-2%cs For %%A in ("%ttFile%") do Set tempTT=%TEMP%\%%~nxA For %%A in ("%csFile%") do Set tempCS=%TEMP%\%%~nxA copy "%ttFile%" "%tempTT% "%COMMONPROGRAMFILES(x86)%\microsoft shared\TextTemplating\11.0\TextTransform.exe" "%tempTT%" fc %tempCS% %csFile% > nul if errorlevel 1 ( :: You can try to insert you check-out command here. "%COMMONPROGRAMFILES(x86)%\microsoft shared\TextTemplating\11.0\TextTransform.exe" "%ttFile%" ) ELSE ( ECHO no change in %csFile% ) del %tempTT% del %tempCS% goto :eof :End 

您可以尝试添加您的签出命令在一行(::您可以尝试….)

在你的项目中将其设置为一个预建立的操作:

 Path-To-Transform.bat "$(ProjectDir)" 

您只需将此命令添加到项目的预生成事件中:

 if $(ConfigurationName) == Debug $(MSBuildToolsPath)\Msbuild.exe /p:CustomBeforeMicrosoftCSharpTargets="$(ProgramFiles)\MSBuild\Microsoft\VisualStudio\v11.0\TextTemplating\Microsoft.TextTemplating.targets" $(ProjectPath) /t:TransformAll 

检查配置= debug,确保在发布模式下不会重新生成代码,例如在TFS构建服务器上进行构建时。

在Visual Studio 2013中,右键单击T4模板并将build属性上的变换设置为true。

有些人为此建立了一个nuget包 。

附注:我从TextTemplate.exe和该包(因为该包调用TextTemplate.exe)而不是从Visual Studio中收到编译错误。 所以显然行为是不一样的。 小心。

编辑: 这最终成为我的问题。

这是我如何加入。 链接 。 基本上建立在一个伟大的博客之上(blogs.clariusconsulting.net/kzu/how-to-transform-t4-templates-on-build-without-installing-a-visual-studio-sdk/不能发布更多的2链接:()我想出了这个.targets文件用于visual studio proj文件。

当你在你的.tt文件里面使用其他的dll-s,并且你想让结果随着dll-s的改变而变化的时候,它是很有用的。

怎么运行的:

  1. 创建tt,将程序集名称=“$(SolutionDir)path \”添加到\ other \ project \ output \ foo.dll中,并将转换和结果设置为预期的
  2. 从.tt中删除程序集引用

  3. 在proj文件里面使用下面的代码来设置构建转换:

     <PropertyGroup> <!-- Initial default value --> <_TransformExe>$(CommonProgramFiles)\Microsoft Shared\TextTemplating\10.0\TextTransform.exe</_TransformExe> <!-- If explicit VS version, override default --> <_TransformExe Condition="'$(VisualStudioVersion)' != ''">$(CommonProgramFiles)\Microsoft Shared\TextTemplating\$(VisualStudioVersion)\TextTransform.exe</_TransformExe> <!-- Cascading probing if file not found --> <_TransformExe Condition="!Exists('$(_TransformExe)')">$(CommonProgramFiles)\Microsoft Shared\TextTemplating\10.0\TextTransform.exe</_TransformExe> <_TransformExe Condition="!Exists('$(_TransformExe)')">$(CommonProgramFiles)\Microsoft Shared\TextTemplating\11.0\TextTransform.exe</_TransformExe> <_TransformExe Condition="!Exists('$(_TransformExe)')">$(CommonProgramFiles)\Microsoft Shared\TextTemplating\12.0\TextTransform.exe</_TransformExe> <!-- Future proof 'til VS2013+2 --> <_TransformExe Condition="!Exists('$(_TransformExe)')">$(CommonProgramFiles)\Microsoft Shared\TextTemplating\13.0\TextTransform.exe</_TransformExe> <_TransformExe Condition="!Exists('$(_TransformExe)')">$(CommonProgramFiles)\Microsoft Shared\TextTemplating\14.0\TextTransform.exe</_TransformExe> <_TransformExe Condition="!Exists('$(_TransformExe)')">$(CommonProgramFiles)\Microsoft Shared\TextTemplating\15.0\TextTransform.exe</_TransformExe> <IncludeForTransform>@(DllsToInclude, '&amp;quot; -r &amp;quot;')</IncludeForTransform> </PropertyGroup> 
    • 第一部分找到TextTransform.exe

    • $(IncludeForTransform)将等于c:\path\to\dll\foo.dll' -rc:\path\to\dll\bar.dll因为这是在命令行上为TextTransform添加引用的方法

        <Target Name="TransformOnBuild" BeforeTargets="BeforeBuild"> <!--<Message Text="$(IncludeForTransform)" />--> <Error Text="Failed to find TextTransform.exe tool at '$(_TransformExe)." Condition="!Exists('$(_TransformExe)')" /> <ItemGroup> <_TextTransform Include="$(ProjectDir)**\*.tt" /> </ItemGroup> <!-- Perform task batching for each file --> <Exec Command="&quot;$(_TransformExe)&quot; &quot;@(_TextTransform)&quot; -r &quot;$(IncludeForTransform)&quot;" Condition="'%(Identity)' != ''" /> </Target> 
    • <_TextTransform Include="$(ProjectDir)**\*.tt" />这将创建项目和子目录中所有tt文件的列表

    • <Exec Command="...为每个找到的.tt文件产生一个类似于"C:\path\to\Transform.exe" "c:\path\to\my\proj\TransformFile.tt" -r"c:\path\to\foo.dll" -r "c:\path\to\bar.dll"

  4. 剩下的唯一的事情就是把路径添加到里面的dll:

      <ItemGroup> <DllsToInclude Include="$(ProjectDir)path\to\foo.dll"> <InProject>False</InProject> </DllsToInclude> <DllsToInclude Include="$(ProjectDir)path\to\bar.dll"> <InProject>False</InProject> </DllsToInclude> </ItemGroup> 

    这里<InProject>False</InProject>从解决方案视图中隐藏这些项目

所以,现在你应该能够生成你的代码构建和更改dll-s。

您可以删除自定义工具(从Visual Studio内部的属性),所以VS不会尝试转换,每次都会惨败。 因为我们在步骤2中删除了程序集引用