Заставьте Visual Studio запускать шаблон T4 при каждой сборке.
-
22-07-2019 - |
Вопрос
Как мне получить шаблон T4 для генерации выходных данных при каждой сборке?В нынешнем виде он восстанавливает его только тогда, когда я вношу изменения в шаблон.
Я нашел другие вопросы, похожие на этот:
Преобразование T4 и порядок сборки в Visual Studio (без ответа)
Как получить файлы 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 при каждой сборке. Блог Олега Сыча описывает, как это сделать. Короче говоря:
<Ол></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" />
Существует отличный пакет NuGet, который делает именно это:
PM> Install-Package Clarius.TransformOnBuild
Подробная информация о пакете может быть найден здесь
Я использовал ответ 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, указанным в шаблоне директивами Сборка .
Затем перейдите в Project Properties проекта, содержащего шаблон T4. Перейдите в События сборки и добавьте следующую Командную строку события перед сборкой :
$(SolutionDir)..\..\tools\RunTemplate.bat $(ProjectDir)MyTemplate $(OutDir)
замена MyTemplate именем вашего файла .tt (т.е. MyTemplate.tt) без расширения .tt. Это приведет к расширению шаблона для создания MyTemplate.cs перед сборкой проекта. Затем фактическая сборка скомпилирует MyTemplate.cs
Недавно нашел этот замечательный плагин VS, Chirpy .
Он не только генерирует ваш T4 при сборке, но и позволяет использовать подход на основе T4 для минимизации JavaScript, CSS и даже позволяет использовать синтаксис LESS для вашего CSS!
Вероятно, самый простой способ - это установить расширение Visual Studio под названием AutoT4 а>. Р>
Он автоматически запускает все шаблоны T4 при сборке.
Предварительная сборка может быть уменьшена до одной строки:
forfiles /p "$(ProjectDir)." /m "*.tt" /s /c "cmd /c echo Transforming @path && \"%CommonProgramFiles(x86)%\Microsoft Shared\TextTemplating\1.2\TextTransform.exe\" @file"
Это преобразует все .tt
файлы в проекте и перечисляет их в выходные данные сборки.
Проверить C: \ Program Files (x86) \ Общие файлы \ Microsoft Shared \ TextTemplating там есть преобразование exe командной строки. Либо напишите задачу MSBuild с пользовательским хостом и выполните преобразование самостоятельно.
Расширение Сет Рино и ДжоэлФан'с ответы, я придумал это.Благодаря этому решению не нужно помнить об изменении события предварительной сборки каждый раз, когда вы добавляете в проект новый файл .tt.
Процедура реализации
- Создайте пакетный файл с именем Transform_all.bat (см. ниже).
- Создайте событие перед сборкой
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 вне каталога проекта, указав другой путь в качестве первого аргумента (то есть заменять"$(ProjectDir)"
с путем, содержащим файлы TT.)Не забудьте также указать правильный путь к
transform_all.bat
пакетный файл.
Например, я поместил его в каталог своего решения, чтобы событие перед сборкой было следующим:"$(SolutionDir)transform_all.bat" "$(ProjectDir)" $(ProjectExt)
Если вы используете Visual Studio 2010, вы можете использовать Visual Studio SDK для моделирования и визуализации: http://code.msdn.microsoft.com/vsvmsdk
Содержит задачи msbuild для выполнения шаблонов T4 во время сборки.
Посмотрите блог Олега для более подробного объяснения: http://www.olegsych.com/2010/04/understanding-t4 -msbuild-интеграция
Эй, мой скрипт также может проанализировать расширение вывода
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)
перед сборкой, и все файлы *.tt в вашем решении будут преобразованы автоматически.
Dynamo.AutoTT сделает то, что вам нужно. Вы можете настроить его для просмотра файлов через регулярные выражения или генерировать при сборке. Он также позволяет указать, какие шаблоны T4 вы хотите запускать.
Вот мое решение - аналогично принятому ответу.У нас возникла проблема с системой контроля версий.Целевые файлы .cs доступны только для чтения, и T4 дал сбой.Вот код, который запускает T4 во временной папке, сравнивает целевые файлы и копирует их только в случае тех же изменений.Это не решает проблему с файлами только для чтения, но, по крайней мере, это происходит не очень часто:
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
Проверка настройки = отладка гарантирует, что вы не будете заново генерировать код в режиме выпуска, например, при сборке на сервере сборки TFS.
В Visual Studio 2013 щелкните правой кнопкой мыши шаблон T4 и установите для свойства transform on build значение true.
Вот как я это сделал. Связь.По сути, основан на отличном блоге ( blogs.clariusconsulting.net/kzu/how-to-transform-t4-templates-on-build-without-installing-a-visual-studio-sdk/ не может публиковать более 2 ссылки :( ) Я придумал это .цели для использования с файлами проектов Visual Studio.
Это полезно, когда вы используете другие библиотеки DLL внутри вашего .tt и хотите, чтобы результат менялся по мере изменения файлов DLL.
Как это работает:
- Создайте tt, добавьте имя сборки="$(SolutionDir)path o\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' -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=""$(_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.
Вы можете удалить специальный инструмент (из свойств внутри Visual Studio), чтобы VS не пыталась каждый раз трансформироваться и терпела неудачу.Поскольку мы удалили ссылки на сборки на шаге 2.
T4Executer делает это для VS2019. Вы можете указать шаблоны, которые будут игнорироваться при сборке, и есть опция выполнения после сборки.
Какой-то парень создал для этого пакет nuget . / р>
Примечание: я получаю ошибки компиляции как из TextTemplate.exe, так и из этого пакета (потому что этот пакет вызывает TextTemplate.exe), но не из Visual Studio. Итак, по-видимому, поведение не то же самое; возглавляет.
РЕДАКТИРОВАТЬ: Это оказалось моей проблемой.
Вы просто устанавливаете пакет NuGet: Clarius.TransformOnBuild
Затем каждый раз, когда вы нажимаете Перестроить проект (или решение), ваши .tt файлы будут запускаться
В Visual Studio 2017 (возможно, и в следующих версиях) вам следует добавить это в событие Pre-build:
"$(DevEnvDir)TextTransform.exe" -out "$(ProjectDir)YourTemplate.cs" "$(ProjectDir)YourTemplate.tt"
п.с.Измените путь к вашему шаблону, если он находится не в корневом каталоге проекта.