Получить Visual Studio для запуска шаблона T4 для каждой сборки

Как мне получить шаблон T4 для генерации вывода на каждой сборке? Как и сейчас, он только восстанавливает его, когда я вношу изменения в шаблон.

Я нашел другие вопросы, подобные этому:

Преобразование T4 и порядок сборки в Visual Studio (без ответа)

Как получить файлы t4 для создания в visual studio? (ответы недостаточно подробны [при этом все еще сложны] и даже не дают полного смысла)

Там должен быть более простой способ сделать это!

Ответ 1

Я использовал ответ JoelFan, чтобы подойти к этому. Мне это нравится, потому что вам не нужно запоминать, чтобы изменить событие pre-build каждый раз, когда вы добавляете в проект новый файл .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

Ответ 2

Я согласен с GarethJ - в VS2010 гораздо проще регенерировать tt шаблоны для каждой сборки. Блог Oleg Sych описывает, как это сделать. Короче говоря:

Что это. Откройте свой проект. При каждом создании все шаблоны *.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" />

Ответ 3

Существует большой пакет NuGet, который выполняет только это:

PM> Install-Package Clarius.TransformOnBuild

Информация о пакете может быть найдена здесь

Ответ 4

Я использовал ответ MarkGr и разработал это решение. Сначала создайте пакетный файл RunTemplate.bat в отдельной папке tools над основной папкой решения. Пакетный файл имеет только строку:

"%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, указанным директивами Assembly в шаблоне.

Затем перейдите в Project Properties проекта, содержащего шаблон T4. Перейдите в События сборки и добавьте следующую командную строку Pre-build event:

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

заменить MyTemplate на имя файла .tt(т.е. MyTemplate.tt) без расширения .tt. Это приведет к расширению шаблона для создания MyTemplate.cs перед созданием проекта. Тогда фактическая сборка будет компилировать MyTemplate.cs

Ответ 5

Недавно был найден этот отличный плагин VS, Chirpy.

Он не только генерирует ваш T4 в сборке, но и позволяет использовать метод T4 для минимизации javascript, CSS и даже позволяет использовать синтаксис LESS для вашего CSS!

Ответ 6

Вероятно, самым простым способом является установка расширения Visual Studio под названием AutoT4.

Он автоматически запускает все шаблоны T4 при создании.

Ответ 7

Предварительная сборка может быть сведена к одной строке:

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"

Конечно, вы можете вытащить это в пакетный файл, на который вы передаете путь к каталогу проекта, если хотите.

NB Путь может потребовать некоторой настройки. Путь выше - там, где VS 2008 установлен на моей машине; но вы можете обнаружить, что номер версии между TextTemplating и TextTransform.exe отличается.

Ответ 8

Отъезд C:\Program Files (x86)\Common Files\Microsoft Shared\TextTemplating там есть трансформация командной строки exe. Альтернативно напишите задачу MSBuild с помощью настраиваемого хоста и сделайте преобразование самостоятельно.

Ответ 9

Развернувшись на Seth Reno и ответы JoelFan, я придумал это. С этим решением не нужно запоминать изменение события предварительной сборки каждый раз, когда вы добавляете в файл новый файл .tt.

Процедура выполнения

  • Создайте пакетный файл с именем transform_all.bat(см. ниже)
  • Создайте событие pre-build transform_all.bat "$(ProjectDir)" $(ProjectExt) для каждого проекта с .tt, который вы хотите создать

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 вне каталога проекта, указав другой путь в качестве первого аргумента ( i.e. заменить "$(ProjectDir)" на путь, содержащий файлы TT).

  • Помните также установить правильный путь к пакетному файлу transform_all.bat.
    Например, я поместил его в каталог решений, поэтому событие предварительной сборки было следующим: "$(SolutionDir)transform_all.bat" "$(ProjectDir)" $(ProjectExt)

Ответ 11

Эй, my script также может анализировать расширение вывода

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) pre-build, и все *.tt файлы в вашем решении будут автоматически преобразованы.

Ответ 12

Dynamo.AutoTT сделает все, что вам нужно. Вы можете настроить его для просмотра файлов с помощью регулярного выражения или генерации при сборке. Он также позволяет указать, какие шаблоны T4 вы хотите вызвать.

Вы можете скачать его здесь: https://github.com/MartinF/Dynamo.AutoTT

Просто создайте его, скопируйте DLL и файлы AddIn в

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

и уходите.

Если вы хотите получить его в VS2012, вам нужно будет изменить файл Dynamo.AutoTT.AddIn и установить версию на 11.0 внутри файла Addin;

Ответ 13

См. ответ mhutch fooobar.com/questions/31146/...

IMHO, это лучший сервер сборки и дружественный для разработчиков вариант.

Ответ 15

Вот мое решение - похоже на принятый ответ. У нас была проблема с нашим контролем источника. Целевые .cs файлы доступны только для чтения и T4 не работает. Вот код, который запускает T4 в папке temp, сравнивает целевые файлы и копирует его только в случае одного и того же изменения. Он не исправляет проблему с файлами 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)"

Ответ 16

Вам просто нужно добавить эту команду в событие предварительной сборки проекта:

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

Проверка конфигурации = debug, убедитесь, что вы не обновляете код в режиме выпуска, когда вы делаете сборку на сервере сборки TFS, например.

Ответ 17

В visual studio 2013 щелкните правой кнопкой мыши шаблон T4 и установите для свойства transform на build значение true.

Ответ 18

Вот как я это сделал. Ссылка. В основном, основываясь на большом блоге (blogs.clariusconsulting.net/kzu/how-to-transform-t4-templates-on-build-without-installing-a-visual-studio-sdk/не может публиковать больше, что 2 Ссылки:() Я придумал этот .targets файл для использования с файлами proj с визуальной студией.

Это полезно, когда вы используете другие dll-s внутри вашего .tt и хотите, чтобы результат изменился по мере изменения dll.

Как это работает:

  • Создайте tt, добавьте путь сборки name= "$ (SolutionDir)\to\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, '&amp;quot; -r &amp;quot;')</IncludeForTransform>
    </PropertyGroup>
    
    • Первая часть находит TextTransform.exe

    • $(IncludeForTransform) будет равно c:\path\to\dll\foo.dll' -r c:\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"

  • Осталось только добавить пути к 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

Ответ 19

T4Executer делает это для VS2019. Вы можете указать шаблоны, которые будут игнорироваться при сборке, и есть опция выполнения после сборки.

Ответ 20

Вы просто устанавливаете пакет NuGet: Clarius.TransformOnBuild

Затем каждый раз, когда вы нажимаете Rebuild project (или Solution), ваши .tt файлы будут запускаться

Ответ 22

В Visual Studio 2017 (возможно, и в следующих версиях) вы должны добавить это в событие Pre-build:

"$(DevEnvDir)TextTransform.exe" -out "$(ProjectDir)YourTemplate.cs" "$(ProjectDir)YourTemplate.tt"

ps Измените путь к вашему шаблону, если он находится не в корневом каталоге проекта.

Ответ 23

У меня была ситуация, когда мне нужно запустить только шаблон .t T4 в сборке проекта. Ни один из ответов не описывает выборочное выполнение шаблонов T4, ниже в статье рассматривается полная конфигурация для

  • Автоматический запуск шаблона T4 при сборке/перестройке проекта или решения
  • Показать сообщения до и после преобразования в окне вывода
  • Журнал список файлов, затронутых этим
  • Настройте для запуска всех шаблонов или только определенных.

Как автоматически запустить пользовательский инструмент для шаблонов T4

Ответ 24

Благодаря GitHub.com/Mono/T4 на данный момент вы можете сделать это как для сборок .NET Core, так и для сборок Visual Studio, добавив это в файл .csproj:

  <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>

Если вы преобразуете свои шаблоны в разные языки программирования, вам нужно добавить что-то вроде <Compile Remove="**\*.vb" /> и <Compile Include="**\*.vb" />, чтобы эти файлы были скомпилированы, даже если вы еще не сгенерировали файлы.

Трюк Remove и Include нужен только для первого поколения, или вы можете сделать XML-код короче, например так:

  <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>

и просто запустите build дважды (в первый раз). Если вы уже сгенерировали файлы, зафиксированные в репозитории, не будет проблем при перестроениях в обоих примерах.

В Visual Studio вы можете захотеть увидеть что-то вроде этого:

enter image description here

вместо этого:

enter image description here

Поэтому добавьте что-то подобное в файл проекта:

  <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>

Полный пример здесь: GitHub.com/Konard/T4GenericsExample (включает создание нескольких файлов из одного шаблона).