Visual studio 让Visual Studio在每个生成上运行T4模板

Visual studio 让Visual Studio在每个生成上运行T4模板,visual-studio,tfs,msbuild,t4,Visual Studio,Tfs,Msbuild,T4,如何获取T4模板以在每次构建时生成其输出?就像现在一样,它只在我更改模板时重新生成它 我发现了其他类似的问题: (未答复) (答案不够详细[虽然仍然很复杂],甚至没有完全的意义) 必须有一个更简单的方法来做到这一点 退房 C:\Program Files(x86)\Common Files\Microsoft Shared\text模板 其中有一个命令行转换exe。或者,使用自定义主机编写MSBuild任务,然后自己进行转换。我使用了MarkGr的答案并开发了此解决方案。首先,在主解决方案文件夹

如何获取T4模板以在每次构建时生成其输出?就像现在一样,它只在我更改模板时重新生成它

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

(未答复)

(答案不够详细[虽然仍然很复杂],甚至没有完全的意义)

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

退房 C:\Program Files(x86)\Common Files\Microsoft Shared\text模板
其中有一个命令行转换exe。或者,使用自定义主机编写MSBuild任务,然后自己进行转换。

我使用了MarkGr的答案并开发了此解决方案。首先,在主解决方案文件夹上方的一个单独的tools文件夹中创建一个名为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是模板中程序集指令引用的任何DLL的路径

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

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

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

如果您使用的是Visual Studio 2010,则可以使用Visual Studio建模和可视化SDK:

其中包含用于在生成时执行T4模板的msbuild任务

查看Oleg的博客了解更多解释:

我用了乔尔凡的答案得出了这个结论。我更喜欢它,因为您不必记得每次向项目添加新的.tt文件时都要修改预构建事件

  • 将TextTransform.exe添加到
    %PATH%
  • 创建了名为transform_all.bat的批处理文件(见下文)
  • 创建预构建事件“
    转换所有…”
transform\u 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
@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

我同意GarethJ——在VS2010中,在每个构建上重新生成tt模板要容易得多。 OlegSych的博客描述了如何做到这一点。简言之:

  • 安装
  • 安装
  • 在文本编辑器中打开项目文件并 添加到文件末尾但在
  • 就这样。打开你的项目。在每次构建中,将重新处理所有*.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" />
    
    
    真的
    
    最近发现了这个很棒的VS插件

    它不仅可以在构建时生成T4,还允许使用基于T4的方法来缩小javascript、CSS,甚至可以减少CSS的语法使用

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

    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\u all.bat$(SolutionDir)
    pre-build事件,解决方案中的所有*.tt文件都将自动转换。

    预构建可以减少到一行:

    forfiles /p "$(ProjectDir)." /m "*.tt" /s /c "cmd /c echo Transforming @path && \"%CommonProgramFiles(x86)%\Microsoft Shared\TextTemplating\1.2\TextTransform.exe\" @file"
    
    这将转换项目中的所有
    .tt
    文件,并将它们列出到生成输出中

    如果不希望生成输出,则必须解决以下问题:

    当然,如果愿意,您可以将其拉入批处理文件,并将项目目录路径传递给该批处理文件


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

    Dynamo.AutoTT将满足您的需要。您可以将其配置为通过正则表达式查看文件或生成内部版本。它还允许您指定要触发的T4模板

    您可以从这里下载:

    只需构建它,将dll和加载项文件复制到

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

    然后你就走了


    如果要在VS2012中运行,需要修改a Dynamo.AutoTT.AddIn文件,并在AddIn文件中将版本设置为11.0

    这是我的解决方案-类似于公认的答案。 我们的源代码管理有问题。目标.cs文件为只读文件,T4出现故障。 下面是代码,它在temp文件夹中运行T4,比较目标文件,并仅在相同更改的情况下复制它。它不会解决只读文件的问题,但至少不会经常出现:

    变身蝙蝠

    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)"
    
    通过扩展和回答,我得出了这个结论。使用此解决方案,无需记住每次向项目添加新的.tt文件时都要修改预构建事件

    实施程序
    • 创建名为transform_all.bat的批处理文件(见下文)
    • 为每个要生成.tt的项目创建预生成事件
      transform_all.bat“$(ProjectDir)”$(ProjectExt)
    transform\u 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
    
    @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\u all.bat
    例如,我将它放在我的解决方案目录中,因此预构建事件如下所示:“$(解决方案
    PM> Install-Package Clarius.TransformOnBuild
    
    <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>
    
     <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>
    
        <ItemGroup>
          <DllsToInclude Include="$(ProjectDir)path\to\foo.dll">
            <InProject>False</InProject>
          </DllsToInclude>
          <DllsToInclude Include="$(ProjectDir)path\to\bar.dll">
            <InProject>False</InProject>
          </DllsToInclude>
        </ItemGroup>
    
    "$(DevEnvDir)TextTransform.exe" -out "$(ProjectDir)YourTemplate.cs" "$(ProjectDir)YourTemplate.tt"
    
      <ItemGroup>
        <DotNetCliToolReference Include="dotnet-t4-project-tool" Version="2.0.5" />
        <TextTemplate Include="**\*.tt" />
      </ItemGroup>
    
      <Target Name="TextTemplateTransform" BeforeTargets="BeforeBuild">
        <ItemGroup>
          <Compile Remove="**\*.cs" />
        </ItemGroup>
        <Exec WorkingDirectory="$(ProjectDir)" Command="dotnet t4 %(TextTemplate.Identity)" />
        <ItemGroup>
          <Compile Include="**\*.cs" />
        </ItemGroup>
      </Target>
    
      <ItemGroup>
        <DotNetCliToolReference Include="dotnet-t4-project-tool" Version="2.0.5" />
        <TextTemplate Include="**\*.tt" />
      </ItemGroup>
    
      <Target Name="TextTemplateTransform" BeforeTargets="BeforeBuild">
        <Exec WorkingDirectory="$(ProjectDir)" Command="dotnet t4 %(TextTemplate.Identity)" />
      </Target>
    
      <ItemGroup>
        <Compile Update="UInt16Class.cs">
          <DependentUpon>UInt16Class.tt</DependentUpon>
        </Compile>
        <Compile Update="UInt32Class.cs">
          <DependentUpon>UInt32Class.tt</DependentUpon>
        </Compile>
        <Compile Update="UInt64Class.cs">
          <DependentUpon>UInt64Class.tt</DependentUpon>
        </Compile>
        <Compile Update="UInt8Class.cs">
          <DependentUpon>UInt8Class.tt</DependentUpon>
        </Compile>
      </ItemGroup>
    
    "$(MSBuildBinPath)\msbuild" $(SolutionPath) /t:$(ProjectName):Transform /p:TransformFile="AppDbContext.tt" /p:CustomAfterMicrosoftCommonTargets="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\TextTemplating\Microsoft.TextTemplating.targets"