Шаблон T4 не преобразуется при сборке

Я использую VisualStudio Ultimate 2012 (обновление 1) в Windows 7. Я могу получить шаблон T4 для создания файла, щелкнув правой кнопкой мыши [tt file] | запустить пользовательский инструмент. Это прекрасно работает! (ура для меня). Это также работает, если я запускаю команду меню: Build | Преобразуйте все шаблоны T4. Но я хочу автоматизации! Я сталкиваюсь с проблемой, когда пытаюсь получить сгенерированный файл кода для каждой сборки, что и является моей целью.
Я посмотрел на это: преобразование T4 и порядок сборки в Visual Studio

это не то, что я хочу. В нем обсуждается использование события перед сборкой. Я хотел, чтобы это было частью сборки.

и это: есть ли способ заставить Visual Studio запустить "Преобразовать все шаблоны" при успешной сборке?

это не то, что я хотел. Здесь обсуждается использование события после сборки.

Затем я нашел это: Понимание T4: Интеграция MSBuild

из блога Олега Сыча:

Отлично! Это то, что я хочу. Хотя его блог обсуждает VS2010, я применил его к VS2012, где это применимо.

Я прошел через каждый из его шагов для реализации этого. Я установил Visual Studio SDK 2012 и Visual Studio SDK для визуализации и моделирования (2012)

Я начал с использования плагина Tangible T4, но, подумав, что с этим возникла проблема, я использовал бета-версию Олега T4 Toolbox. К сожалению, с любым из них я, казалось, получил те же результаты: ошибка со сборкой.

Я следовал его инструкциям на его сайте и перечитал все шаги и части. Я искал в течение нескольких дней, и теперь мой первый пост здесь. Я застрял. Спасибо за поиск...

Напомним: я получаю сообщение об ошибке при сборке в Visual Studio 2012 или при запуске msbuild из командной строки (но опять же не при запуске Custom Tool или использовании ручного Transform All T4 Templates - оба из них работают нормально).

Вот мой t4template называется s_code.tt:

<#@ template  debug="true" hostSpecific="true" language="C#" #>
<#@ output extension=".js" #>
<#@ assembly name="System.Core" #>
<#@ assembly name="System.Xml" #>
<#@ assembly name="EnvDTE" #>
<#@ assembly name="EnvDTE80" #>
<#@ assembly name="Microsoft.VisualStudio.Shell.Interop.8.0" #>
<#@ import namespace="System.Diagnostics" #>
<#@ import namespace="System" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.IO" #>
<#@ import namespace="EnvDTE" #>
<#@ import namespace="EnvDTE80" #>
<#@ import namespace="Microsoft.VisualStudio.TextTemplating" #>
<#@ import namespace="Microsoft.VisualStudio.Shell.Interop" #>


<#
    IServiceProvider serviceProvider = (IServiceProvider)Host;
    EnvDTE.DTE dte = (EnvDTE.DTE)serviceProvider.GetService(typeof(EnvDTE.DTE));
    var configName = dte.Solution.SolutionBuild.ActiveConfiguration.Name;
    string filename = this.Host.ResolvePath("s_code_source.txt");
    string[] lines = File.ReadAllLines(filename);
    bool isAccountFound = false;
    int linecount = lines.Length;
    int currentline = 0;
    for (int i=0;i<linecount;i++)
    {
        if (Contains_S_Account(lines[i]))
        {
            if (configName.ToUpper() == "DEBUG")
            {
                    WriteLine("var s_account = \"macudev2\"");
            }
            else if (configName.ToUpper() == "RELEASE")
             {
                   WriteLine("var s_account = \"macudev\"");
             }

            currentline = i;
            isAccountFound = true;
        }
        else
        {
            WriteLine(lines[i]);
        }
    }
    for (int i=currentline;i<linecount;i++)
    {
        WriteLine(lines[i]);
    }


#>

<#+
private bool Contains_S_Account(string line)
{
    if (line.ToLower().Contains("var s_account"))
    {
        return true;
    }
    else
    {
        return false;
    }
}
#>

Вот мой .csproj файл:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProductVersion>
    </ProductVersion>
    <SchemaVersion>2.0</SchemaVersion>
    <ProjectGuid>{0A44E136-F4A4-4B31-95DD-2C8A79FDFAF4}</ProjectGuid>
    <ProjectTypeGuids>{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
    <OutputType>Library</OutputType>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <RootNamespace>Macu.Content</RootNamespace>
    <AssemblyName>Macu.Content</AssemblyName>
    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
    <UseIISExpress>true</UseIISExpress>
    <IISExpressSSLPort />
    <IISExpressAnonymousAuthentication />
    <IISExpressWindowsAuthentication />
    <IISExpressUseClassicPipelineMode />
    <TargetFrameworkProfile />
    <TransformOnBuild>True</TransformOnBuild>
    <IncludeFolders>$(MSBuildProjectDirectory)\Include</IncludeFolders>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <OutputPath>bin\</OutputPath>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <OutputPath>bin\</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="EnvDTE, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
      <EmbedInteropTypes>True</EmbedInteropTypes>
    </Reference>
    <Reference Include="envdte80, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
      <EmbedInteropTypes>True</EmbedInteropTypes>
    </Reference>
    <Reference Include="Microsoft.CSharp" />
    <Reference Include="Microsoft.VisualStudio.Shell.Interop.10.0, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
      <EmbedInteropTypes>True</EmbedInteropTypes>
    </Reference>
    <Reference Include="Microsoft.VisualStudio.TextTemplating.11.0, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
    <Reference Include="System" />
    <Reference Include="System.Xml" />
  </ItemGroup>
  <ItemGroup>
    <Content Include="shared\script\s_code.js">
      <AutoGen>True</AutoGen>
      <DesignTime>True</DesignTime>
      <DependentUpon>s_code.tt</DependentUpon>
    </Content>
    <Content Include="shared\script\s_code_source.txt" />
    <Content Include="Web.config" />
  </ItemGroup>
  <ItemGroup>
    <Compile Include="Properties\AssemblyInfo.cs" />
  </ItemGroup>
  <ItemGroup>
    <Content Include="shared\script\s_code.tt">
      <Generator>TextTemplatingFileGenerator</Generator>
      <LastGenOutput>s_code.js</LastGenOutput>
      <Parameters>
        &lt;%3fxml version="1.0" encoding="utf-16"%3f&gt;
        &lt;ArrayOfParameterStorage xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" /&gt;
      </Parameters>
    </Content>
    <None Include="Properties\PublishProfiles\Local.pubxml" />
    <None Include="Web.Debug.config">
      <DependentUpon>Web.config</DependentUpon>
    </None>
    <None Include="Web.Release.config">
      <DependentUpon>Web.config</DependentUpon>
    </None>
  </ItemGroup>
  <ItemGroup>
    <T4ReferencePath Include="$(VsInstallDir)PublicAssemblies\" />
  </ItemGroup>
  <ItemGroup>
    <Folder Include="shared\images\" />
  </ItemGroup>
  <ItemGroup />
  <ItemGroup>
    <Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" />
  </ItemGroup>
  <PropertyGroup>
    <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
    <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
  </PropertyGroup>
  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
  <Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v11.0\TextTemplating\Microsoft.TextTemplating.targets" />
  <Import Project="$(VSToolsPath)\WebApplications\Microsoft.WebApplication.targets" Condition="'$(VSToolsPath)' != ''" />
  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" Condition="false" />
  <ProjectExtensions>
    <VisualStudio>
      <FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}">
        <WebProjectProperties>
          <UseIIS>True</UseIIS>
          <AutoAssignPort>True</AutoAssignPort>
          <DevelopmentServerPort>30698</DevelopmentServerPort>
          <DevelopmentServerVPath>/</DevelopmentServerVPath>
          <IISUrl>http://localhost:50012/</IISUrl>
          <NTLMAuthentication>False</NTLMAuthentication>
          <UseCustomServer>False</UseCustomServer>
          <CustomServerUrl>
          </CustomServerUrl>
          <SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile>
        </WebProjectProperties>
      </FlavorProperties>
    </VisualStudio>
  </ProjectExtensions>
  <PropertyGroup>
    <PreBuildEvent>
    </PreBuildEvent>
  </PropertyGroup>
  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
       Other similar extension points exist, see Microsoft.Common.targets.
  <Target Name="BeforeBuild">
  </Target>
  <Target Name="AfterBuild">
  </Target>
  -->
</Project>

Вот ошибка, которую я вижу после запуска MSBuild из командной строки:

C:\Users\[myUserName]\Documents\Visual Studio 2012\Projects\Macu.Content\Macu.Conten
t>msbuild macu.content.csproj /t:TransformAll
Microsoft (R) Build Engine version 4.0.30319.17929
[Microsoft .NET Framework, version 4.0.30319.17929]
Copyright (C) Microsoft Corporation. All rights reserved.

Build started 1/17/2013 2:16:59 PM.
Project "C:\Users\[myUserName]\Documents\Visual Studio 2012\Projects\Macu.Content\M
acu.Content\macu.content.csproj" on node 1 (TransformAll target(s)).
ExecuteTransformations:
  Performing incremental T4 transformation
  Calculating whether transformed output is out of date...
  Transforming template shared\script\s_code.tt...
C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v11.0\TextTemplating\Micr
osoft.TextTemplating.targets(396,5): warning : Compiling transformation: The va
riable 'isAccountFound' is assigned but its value is never used. Line=24, Colum
n=7 [C:\Users\[myUserName]\Documents\Visual Studio 2012\Projects\Macu.Content\Macu.
Content\macu.content.csproj]
C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v11.0\TextTemplating\Micr
osoft.TextTemplating.targets(396,5): error : Running transformation: System.Nul
lReferenceException: Object reference not set to an instance of an object.\r [C
:\Users\[myUserName]\Documents\Visual Studio 2012\Projects\Macu.Content\Macu.Conten
t\macu.content.csproj]
C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v11.0\TextTemplating\Micr
osoft.TextTemplating.targets(396,5): error :    at Microsoft.VisualStudio.TextT
emplating7D294BC599798219F70D124BB1976BCDFB50B07280E2004F9365EC71A617D68D059E43
6CBD1AD344727611A619EE41F939B60372B3E16565CA2D4E4B40FBC5C7.GeneratedTextTransfo
rmation.TransformText() in c:\Users\[myUserName]\Documents\Visual Studio 2012\Proje
cts\Macu.Content\Macu.Content\shared\script\s_code.tt:line 21. Line=21, Column=
0 [C:\Users\[myUserName]\Documents\Visual Studio 2012\Projects\Macu.Content\Macu.Co
ntent\macu.content.csproj]
Done Building Project "C:\Users\[myUserName]\Documents\Visual Studio 2012\Projects\
Macu.Content\Macu.Content\macu.content.csproj" (TransformAll target(s)) -- FAIL
ED.


Build FAILED.

"C:\Users\[myUserName]\Documents\Visual Studio 2012\Projects\Macu.Content\Macu.Cont
ent\macu.content.csproj" (TransformAll target) (1) ->
(ExecuteTransformations target) ->
  C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v11.0\TextTemplating\Mi
crosoft.TextTemplating.targets(396,5): warning : Compiling transformation: The
variable 'isAccountFound' is assigned but its value is never used. Line=24, Col
umn=7 [C:\Users\[myUserName]\Documents\Visual Studio 2012\Projects\Macu.Content\Mac
u.Content\macu.content.csproj]


"C:\Users\[myUserName]\Documents\Visual Studio 2012\Projects\Macu.Content\Macu.Cont
ent\macu.content.csproj" (TransformAll target) (1) ->
(ExecuteTransformations target) ->
  C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v11.0\TextTemplating\Mi
crosoft.TextTemplating.targets(396,5): error : Running transformation: System.N
ullReferenceException: Object reference not set to an instance of an object.\r
[C:\Users\[myUserName]\Documents\Visual Studio 2012\Projects\Macu.Content\Macu.Cont
ent\macu.content.csproj]
C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v11.0\TextTemplating\Micr
osoft.TextTemplating.targets(396,5): error :    at Microsoft.VisualStudio.TextT
emplating7D294BC599798219F70D124BB1976BCDFB50B07280E2004F9365EC71A617D68D059E43
6CBD1AD344727611A619EE41F939B60372B3E16565CA2D4E4B40FBC5C7.GeneratedTextTransfo
rmation.TransformText() in c:\Users\[myUserName]\Documents\Visual Studio 2012\Proje
cts\Macu.Content\Macu.Content\shared\script\s_code.tt:line 21. Line=21, Column=
0 [C:\Users\[myUserName]\Documents\Visual Studio 2012\Projects\Macu.Content\Macu.Co
ntent\macu.content.csproj]

    1 Warning(s)
    1 Error(s)

Time Elapsed 00:00:01.04

Можете ли вы увидеть что-то, что я делаю, что вызывает ошибку, и знаете ли вы, как ее исправить, чтобы я мог использовать msbuild и не сталкиваться с этой ошибкой?

4 ответа

Решение

Я боюсь, что вы не можете успешно запускать шаблоны во время сборки, которые используют переменную Host для доступа к службам IDE, таким как DTE, так как хост msbuild T4 предназначен для работы как из командной строки, так и встраивается в IDE, и как таковая, не предоставляет глобального поставщика услуг или DTE шаблонам. То же самое относится и к texttransform.exe, простому узлу командной строки.

У одного из наших клиентов была точно такая же проблема, и GarethJ прав, что это невозможно сделать "из коробки".

Тем не менее, вы можете написать свой собственный инструмент "TextTransform.exe", который обеспечивает API автоматизации Visual Studio для шаблонов довольно легко. Все, что вам нужно сделать, это реализовать интерфейсы ITextTemplatingEngineHost и IServiceProvider и возвращать экземпляр интерфейса DTE, когда он запрашивается.

Тем не менее, мы написали пост в блоге об этом сценарии, а также опубликовали Tool = Source Code.

Одно замечание: вам нужна правильно лицензированная установка Visual Studio на вашем сервере сборки, чтобы это работало.

Matthid @ AIT

В осязаемом редакторе T4 есть функция, которая называется Transform On Build, которая позволяет пометить шаблон как "трансформировать при сборке" в сетке свойств исследователей решений. Это преобразует шаблон каждый раз, когда вы строите в Visual Studio (не на сервере сборки). Там ваши шаблоны также имеют доступ к EnvDTE и другим переменным Visual Studio. Смотрите: http://t4-editor.tangible-engineering.com/blog/transforming-t4-templates-on-build.html

Я недавно столкнулся с этой проблемой в процессе сборки (не использовал DTE). Я решил ее, убедившись, что на моем компьютере был только 1 texttransform.exe. По какой-то причине в IDE использовалась последняя версия texttransform.exe и msbuild старый.

Другие вопросы по тегам