获取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的博客介绍了如何做到这一点。 简而言之:
- 安装Visual Studio SDK
- 安装Visual Studio 2010建模和可视化SDK
- 在文本编辑器项目文件中打开,并添加到文件的末尾,但在
</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在我的机器上安装它的地方; 但是您可能会发现TextTemplating
和TextTransform.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
笔记
-
文本转换假设T4模板中的代码与您的项目类型是相同的语言。 如果这种情况不适用于您,那么您将不得不将
$(ProjectExt)
参数替换为您想要代码生成的文件的扩展名。 -
.TT
文件必须在项目目录中,否则它们将不会生成。 您可以通过指定不同的路径作为第一个参数( 即用包含TT文件的路径替换"$(ProjectDir)"
来在工程目录之外生成TT文件。 -
还请记住将正确的路径设置为
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的改变而变化的时候,它是很有用的。
怎么运行的:
- 创建tt,将程序集名称=“$(SolutionDir)path \”添加到\ other \ project \ output \ foo.dll中,并将转换和结果设置为预期的
-
从.tt中删除程序集引用
-
在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, '&quot; -r &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=""$(_TransformExe)" "@(_TextTransform)" -r "$(IncludeForTransform)"" 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"
-
-
剩下的唯一的事情就是把路径添加到里面的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中删除了程序集引用