在TFS 2013上构建失败,但本地却可以。

26

当我提交代码时,TFS 2013 自动构建了解决方案。在本地的 VS 2013 中没问题,但在 TFS 中失败了。

这里是概要。

Summary
FTPProcessor | Any CPU
1 error(s), 56 warning(s) 
$/xxxx/NewServiceHost/New-Branch/NewServiceHost/packageRestore.proj - 0 error(s), 0 warning(s) 
$/xxxx/NewServiceHost/New-Branch/GenericWindowsServices.sln - 1 error(s), 56 warning(s) 
C:\Builds\1\xxxx\FTP Processor (New)\src\.nuget\nuget.targets (71): The task factory "CodeTaskFactory" could not be loaded from the assembly "C:\Program Files (x86)\MSBuild\12.0\bin\amd64\Microsoft.Build.Tasks.v4.0.dll". Could not load file or assembly 'file:///C:\Program Files (x86)\MSBuild\12.0\bin\amd64\Microsoft.Build.Tasks.v4.0.dll' or one of its dependencies. The system cannot find the file specified.
Other Errors 
1 error(s) 
Exception Message: MSBuild error 1 has ended this build. You can find more specific information about the cause of this error in above messages. (type BuildProcessTerminateException) Exception Stack Trace: at System.Activities.Statements.Throw.Execute(CodeActivityContext context) at System.Activities.CodeActivity.InternalExecute(ActivityInstance instance, ActivityExecutor executor, BookmarkManager bookmarkManager) at System.Activities.Runtime.ActivityExecutor.ExecuteActivityWorkItem.ExecuteBody(ActivityExecutor executor, BookmarkManager bookmarkManager, Location resultLocation)
4个回答

55

你的TFS 2013构建服务器正在使用MSBuild 12.0,其中 CodeTasksFactory 存在于 Microsoft.Build.Tasks.v12.0.dll 中,而不是 Microsoft.Build.Tasks.v4.0.dll。

理想情况下,您应该执行以下操作:

1)打开 NuGet.targets 文件: C:\Builds\1\xxxx\FTP Processor (New)\src.nuget\nuget.targets

2)确定引用旧 DLL 的任务。

<UsingTask AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll" TaskFactory="CodeTaskFactory" >
...

3) 然后这样未来可以保持兼容性:

<UsingTask AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v$(MSBuildToolsVersion).dll" TaskFactory="CodeTaskFactory" >
...

1
你发现了一个事实,我可以更改nuget.targets文件。但是我们需要更改csproj文件中的ToolsVersion值吗?实际上,我的本地机器使用VS 2013,我的TFS使用旧版本。 - user1108948
你可以更改.csproj文件中的值,但另一种选择是在调用msbuild.exe时使用toolsversion开关进行覆盖。http://msdn.microsoft.com/en-us/library/bb383985.aspx - Nicodemeus
5
我必须进行这个更改并修复我的项目文件,将ToolsVersion从"4.0"改为"12.0"。 - ProVega

4

2

经过许多研究并尝试了许多“技巧”后,我开始了解nuget restore的确切机制。原来,自nuget 2.7+以来,一切都已经改变,你不再需要包括“.nuget”文件夹和相关的nuget.exe和nuget.target。

为了修复我的构建过程并使用最新的推荐方法,我采取了以下步骤:

  • 将nuget.config移动到与.sln文件相同的文件夹路径
  • 完全删除“.nuget”文件夹
  • 在.sln文件中删除对该文件夹的引用
  • 从任何.csproj文件中删除以下行

--

<RestorePackages>true</RestorePackages>
<Import Project="$(SolutionDir)\.nuget\nuget.targets" />
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />

--

如果您的项目解决方案包含许多文件,或者您正在处理使用Visual Studio 2013及以前版本构建的许多项目,则可能需要花费一些时间。

好消息是,有一个PowerShell脚本可以递归地应用上述内容到任何文件夹中:

简而言之,它会撤消“启用NuGet软件包还原”功能,使新的软件包还原方法能够正常工作。

在Visual Studio 2013中,自动软件包还原成为IDE(和TFS构建流程)的一部分。此方法比旧的msbuild集成软件包还原更可靠。它不要求您将nuget.exe检入到每个解决方案中,并且不需要任何其他的msbuild目标。但是,如果您的项目中存在与旧软件包还原方法相关的文件,则Visual Studio将跳过自动软件包还原。(这种行为很快就会改变,希望它能做到)。

您可以使用此脚本删除nuget.exe、nuget.targets以及所有与nuget.targets相关的项目和解决方案引用,以便利用自动软件包还原。它或多或少地自动化了此处描述的过程。

它将递归遍历您从脚本中运行的目录,并对其中可能存在的任何解决方案进行操作。请小心并享受乐趣!(不负责任何损坏)

关于这个主题的一些好链接:


0

我曾经遇到过类似的问题。由于我们需要构建一些旧的Delphi.net代码,所以我们被迫使用框架附带的较旧版本的msbuild,而不是Visual Studio 2015附带的v14版本。我们的vcxproj文件会触发一些自动代码分析目标,其中有一个任务依赖于Microsoft.Build.Tasks.v12.0.dll。我能够通过将其复制并粘贴到vcxproj的顶部并调整dll路径来覆盖该任务。原始任务可以在“C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v14.0\CodeAnalysis\Microsoft.CodeAnalysis.Targets”中找到。换句话说,您可能可以在项目中覆盖问题任务。

<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

  <!-- override a task which we can't use with the old msbuild -->
  <UsingTask TaskName="SetEnvironmentVariable" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll">
    <ParameterGroup>
      <EnvKey ParameterType="System.String" Required="true" />
      <EnvValue ParameterType="System.String" Required="true" />
    </ParameterGroup>
    <Task>
      <Using Namespace="System" />
      <Code Type="Fragment" Language="cs">
        <![CDATA[
            try {
                Environment.SetEnvironmentVariable(EnvKey, EnvValue, System.EnvironmentVariableTarget.Process);
            }
            catch  {
            }
        ]]>
      </Code>
    </Task>
  </UsingTask>  

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