T4模板无法随构建转换

17
我正在使用Windows 7上的VisualStudio Ultimate 2012(更新1)。 我可以通过右键单击[tt文件] | 运行自定义工具来生成T4模板文件。这很好用! 如果我运行菜单命令:Build | Transform All T4 Templates,它也可以正常工作。但我想要自动化! 当我尝试在每次构建时生成生成的代码文件时,遇到了问题 - 这是我的目标。 我查看了这个: Visual Studio中的T4转换和构建顺序 这不是我想要的。它讨论了使用预构建构建事件。我希望它成为构建的一部分。 还有这个: 是否有办法让Visual Studio在成功构建后运行“Transform All Templates”? 这也不是我想要的。它讨论了使用后构建事件。

然后我找到了这个:
理解 T4:MSBuild 集成

来自 Oleg Sych's 博客

太好了!这正是我想要的。虽然他的博客讨论的是 VS2010,但我已经根据适用情况将其应用于 VS2012。

我按照他的每个实现步骤进行了操作。
我安装了 Visual Studio SDK 2012Visual Studio Visualization and Modeling SDK (2012)

我开始使用 Tangible T4 插件,但认为存在问题,于是我使用了 Oleg 的 T4 Toolbox Beta。遗憾的是,无论哪种方式,我似乎都得到了相同的结果:构建错误。

我按照他网站上的指示重新阅读了所有步骤和部分。我已经研究了几天,现在是我在这里的第一篇帖子。我陷入了困境。谢谢您的关注...

回顾一下: 当我在Visual Studio 2012中构建或从命令行运行msbuild时,会出现错误(但是再次运行Custom Tool或使用手动Transform All T4 Templates时不会出现错误 - 这两个都可以正常工作)。
这是我的名为s_code.tt的t4template:
<#@ 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而不会遇到这个错误吗?


我同意@weakish的观点,AlexKM所做的更改并没有改善问题。将文本从“我是”更改为“我是”似乎不值得被接受为必要更改。为什么要强迫我使用缩略语?而将短语“提前致谢”谴责为“无用信息”,真的吗?我一直认为表达感谢在这里甚至是社交上可接受的,因为我以前曾经这样做过而没有受到责备。困惑。 :-| - Lorne Redmond
也许我没有仔细阅读整个线程,但解决方案不是切换到运行时t4模板而不是设计时吗? - Michal Hosala
感谢您的输入,很抱歉回复晚了。老实说,使用今天的工具,您的方法似乎更为合理。在撰写这个问题时,我没有看到VS2012(三年前)中明确的选项。可能自那以后T4文本模板已经成熟了,而您提供的链接是针对VS2015的。 - Lorne Redmond
4个回答

23

很抱歉,您无法成功地在构建时运行使用Host变量获取IDE服务(如DTE)的模板,因为msbuild T4主机旨在同时从命令行和IDE中进行构建,并且因此不会向模板公开全局服务提供程序或DTE。这对于texttransform.exe,简单的命令行主机也是如此。


哎呀,现在有意义了。我需要重新考虑我的方法。非常感谢您花时间审查我的问题并提供有意义的答案。 - Lorne Redmond
6
因为我在谷歌上搜索不佳,所以花了很长时间才找到这个直截了当的答案。我想在每次构建时在我的 ASP.NET MVC 项目中对 T4MVC.tt 运行自定义工具,但是我找到的任何扩展都不能在 VS2012 上正确工作(例如,AutoT4MVC 在删除控制器后再次构建时会导致错误),而我找到的任何预构建解决方案都为这个简单问题带来了太多麻烦。因此,我决定设置一个快捷键“Build.TransformAllT4Templates”,并养成在按下 Ctrl+Shift+B 之前先按下 Ctrl+Shift+T 的习惯。 - Michael Nelson

3

我们的一个客户也遇到了同样的问题,GarethJ是正确的,这不能通过开箱即用的方式实现。

但是,你可以很容易地编写自己的 "TextTransform.exe" 工具,它提供了 Visual Studio Automation API 给模板使用。你只需要实现 ITextTemplatingEngineHostIServiceProvider 接口,并在请求时返回 DTE 接口的实例即可。

话虽如此:我们写了一篇博客文章关于这种情况,并且也发布了工具=源代码

但需要注意的是:你需要在构建服务器上拥有合法许可的Visual Studio安装才能使其正常运行。

matthid @ AIT


2
在实用的T4编辑器中,有一个高级功能叫做“构建时转换”,它允许您在解决方案资源管理器的属性网格中将模板标记为“构建时转换”。这样,每次在Visual Studio(而不是构建服务器)内构建时,都会对模板进行转换。此外,您的模板还可以访问EnvDTE和其他Visual Studio变量。 参见:http://t4-editor.tangible-engineering.com/blog/transforming-t4-templates-on-build.html

1

最近在我的构建过程中(没有使用 DTE),我遇到了这个问题。我通过确保我的电脑上只有一个 texttransform.exe 来解决它。由于某种原因,IDE 使用了较新版本的 texttransform.exe,而 msbuild 使用了旧版本。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接