使用工具12.0构建期间的ArgumentOutOfRangeException

时间:2017-03-27 15:37:20

标签: msbuild tfs2015 msbuildextensionpack

我们有一个(旧的)构建定义正在使用TFS 2015上的UpgradeTemplate.xaml(以及具有一堆自定义操作的基础TFSBuild.proj)。因此,正确实现构建现代化的任务需要时间。

我想破解UpgradeTemplate以添加C#6 / VB14支持而无需完全重写构建定义,以保持开发人员的满意。

我尝试编辑UpgradeTemplate.xaml以在TfsBuild上添加ToolPath属性。但是,既然我已经这样做了,几乎所有的项目都会出现以下错误:

  

ArgumentOutOfRangeException:索引和长度必须引用字符串中的位置。参数名称:长度

经过调查,这些项目中的代码行如下所示:

<MSBuild.ExtensionPack.VisualStudio.TfsVersion TaskAction="GetVersion" 
    BuildName="$(BuildDefinition)" TfsBuildNumber="$(BuildNumber)" 
    VersionFormat="DateTime" DateFormat="MMdd" Major="$(MajorVersion)" 
    Minor="$(MinorVersion)">

vbproj上由Message个任务打印出来的这些变量的值:

  

BuildDefinition:MyBuild-Testing
  BuildNumber:57902
  MajorVersion:43
  MinorVersion:2

构建服务器在安装的MSBuild ExtensionPack上安装了版本3.5.10。

如何解决此问题?我正在使用新的构建定义对此进行测试,以允许开发人员在我进行此设置时继续工作,因此如果可能破坏现有构建,我不希望将ExtensionPack替换为最新版本(如果可能)

升级模板

<Activity mc:Ignorable="sad" x:Class="TfsBuild.Process" xmlns="http://schemas.microsoft.com/netfx/2009/xaml/activities" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mtbc="clr-namespace:Microsoft.TeamFoundation.Build.Client;assembly=Microsoft.TeamFoundation.Build.Client" xmlns:mtbw="clr-namespace:Microsoft.TeamFoundation.Build.Workflow;assembly=Microsoft.TeamFoundation.Build.Workflow" xmlns:mtbwa="clr-namespace:Microsoft.TeamFoundation.Build.Workflow.Activities;assembly=Microsoft.TeamFoundation.Build.Workflow" xmlns:mtbwt="clr-namespace:Microsoft.TeamFoundation.Build.Workflow.Tracking;assembly=Microsoft.TeamFoundation.Build.Workflow" xmlns:mtvc="clr-namespace:Microsoft.TeamFoundation.VersionControl.Client;assembly=Microsoft.TeamFoundation.VersionControl.Client" xmlns:mva="clr-namespace:Microsoft.VisualBasic.Activities;assembly=System.Activities" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:sad="http://schemas.microsoft.com/netfx/2009/xaml/activities/presentation" xmlns:sad1="clr-namespace:System.Activities.Debugger;assembly=System.Activities" xmlns:scg="clr-namespace:System.Collections.Generic;assembly=mscorlib" xmlns:this="clr-namespace:TfsBuild;" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <x:Members>
    <x:Property Name="ConfigurationFolderPath" Type="InArgument(x:String)" />
    <x:Property Name="AgentSettings" Type="InArgument(mtbwa:AgentSettings)" />
    <x:Property Name="MSBuildArguments" Type="InArgument(x:String)" />
    <x:Property Name="MSBuildPlatform" Type="InArgument(mtbwa:ToolPlatform)" />
    <x:Property Name="DoNotDownloadBuildType" Type="InArgument(x:Boolean)" />
    <x:Property Name="LogFilePerProject" Type="InArgument(x:Boolean)" />
    <x:Property Name="SourcesSubdirectory" Type="InArgument(x:String)" />
    <x:Property Name="BinariesSubdirectory" Type="InArgument(x:String)" />
    <x:Property Name="TestResultsSubdirectory" Type="InArgument(x:String)" />
    <x:Property Name="RecursionType" Type="InArgument(mtvc:RecursionType)" />
    <x:Property Name="Verbosity" Type="InArgument(mtbw:BuildVerbosity)" />
    <x:Property Name="Metadata" Type="mtbw:ProcessParameterMetadataCollection" />
    <x:Property Name="SupportedReasons" Type="mtbc:BuildReason" />
  </x:Members>
  <this:Process.ConfigurationFolderPath>
    <InArgument x:TypeArguments="x:String" />
  </this:Process.ConfigurationFolderPath>
  <this:Process.AgentSettings>[New Microsoft.TeamFoundation.Build.Workflow.Activities.AgentSettings() With {.MaxWaitTime = New System.TimeSpan(4, 0, 0), .MaxExecutionTime = New System.TimeSpan(0, 0, 0), .TagComparison = Microsoft.TeamFoundation.Build.Workflow.Activities.TagComparison.MatchExactly }]</this:Process.AgentSettings>
  <this:Process.MSBuildArguments>
    <InArgument x:TypeArguments="x:String" />
  </this:Process.MSBuildArguments>
  <this:Process.MSBuildPlatform>[Microsoft.TeamFoundation.Build.Workflow.Activities.ToolPlatform.Auto]</this:Process.MSBuildPlatform>
  <this:Process.DoNotDownloadBuildType>[False]</this:Process.DoNotDownloadBuildType>
  <this:Process.LogFilePerProject>[False]</this:Process.LogFilePerProject>
  <this:Process.SourcesSubdirectory>
    <InArgument x:TypeArguments="x:String" />
  </this:Process.SourcesSubdirectory>
  <this:Process.BinariesSubdirectory>
    <InArgument x:TypeArguments="x:String" />
  </this:Process.BinariesSubdirectory>
  <this:Process.TestResultsSubdirectory>
    <InArgument x:TypeArguments="x:String" />
  </this:Process.TestResultsSubdirectory>
  <this:Process.RecursionType>[Microsoft.TeamFoundation.VersionControl.Client.RecursionType.OneLevel]</this:Process.RecursionType>
  <this:Process.Verbosity>[Microsoft.TeamFoundation.Build.Workflow.BuildVerbosity.Normal]</this:Process.Verbosity>
  <this:Process.Metadata>
    <mtbw:ProcessParameterMetadataCollection />
  </this:Process.Metadata>
  <this:Process.SupportedReasons>All</this:Process.SupportedReasons>
  <mva:VisualBasic.Settings>Assembly references and imported namespaces serialized as XML namespaces</mva:VisualBasic.Settings>
  <Sequence mtbwt:BuildTrackingParticipant.Importance="None">
    <Sequence.Variables>
      <Variable x:TypeArguments="mtbc:IBuildDetail" Name="BuildDetail" />
    </Sequence.Variables>
    <mtbwa:GetBuildDetail DisplayName="Get the Build" Result="[BuildDetail]" />
    <mtbwa:InvokeForReason DisplayName="Update Build Number for Triggered Builds" Reason="Triggered">
      <mtbwa:UpdateBuildNumber BuildNumberFormat="[&quot;$(BuildDefinitionName)_$(Date:yyyyMMdd)$(Rev:.r)&quot;]" DisplayName="Update Build Number" />
    </mtbwa:InvokeForReason>
    <mtbwa:AgentScope DisplayName="Run On Agent" MaxExecutionTime="[AgentSettings.MaxExecutionTime]" MaxWaitTime="[AgentSettings.MaxWaitTime]" ReservationSpec="[AgentSettings.GetAgentReservationSpec()]">
      <mtbwa:AgentScope.Variables>
        <Variable x:TypeArguments="x:String" Name="buildDirectory" />
      </mtbwa:AgentScope.Variables>
      <mtbwa:GetBuildDirectory DisplayName="Get the Build Directory" Result="[buildDirectory]" />
      <If Condition="[Not String.IsNullOrEmpty(ConfigurationFolderPath)]" DisplayName="If Not String.IsNullOrEmpty(ConfigurationFolderPath)">
        <If.Then>
          <mtbwa:TfsBuild BinariesSubdirectory="[BinariesSubdirectory]" BuildDirectory="[buildDirectory]" CommandLineArguments="[MSBuildArguments]" ConfigurationFolderPath="[ConfigurationFolderPath]" DisplayName="Run TfsBuild for Configuration Folder" DoNotDownloadBuildType="[DoNotDownloadBuildType]" LogFilePerProject="[LogFilePerProject]" RecursionType="[RecursionType]" SourcesSubdirectory="[SourcesSubdirectory]" TestResultsSubdirectory="[TestResultsSubdirectory]" ToolPath="C:\Program Files (x86)\MSBuild\12.0\Bin\" ToolPlatform="[MSBuildPlatform]" Verbosity="[Verbosity]" />
        </If.Then>
      </If>
      <If Condition="[BuildDetail.CompilationStatus = Microsoft.TeamFoundation.Build.Client.BuildPhaseStatus.Unknown]" DisplayName="If CompilationStatus = Unknown">
        <If.Then>
           <mtbwa:SetBuildProperties CompilationStatus="[Microsoft.TeamFoundation.Build.Client.BuildPhaseStatus.Succeeded]" DisplayName="Set CompilationStatus to Succeeded" PropertiesToSet="CompilationStatus" />
        </If.Then>
      </If>
      <If Condition="[BuildDetail.TestStatus = Microsoft.TeamFoundation.Build.Client.BuildPhaseStatus.Unknown]" DisplayName="If TestStatus = Unknown">
        <If.Then>
          <mtbwa:SetBuildProperties DisplayName="Set TestStatus to Succeeded" PropertiesToSet="TestStatus" TestStatus="[Microsoft.TeamFoundation.Build.Client.BuildPhaseStatus.Succeeded]" />
        </If.Then>
      </If>
    </mtbwa:AgentScope>
    <mtbwa:InvokeForReason Reason="CheckInShelveset">
      <mtbwa:CheckInGatedChanges DisplayName="Check In Gated Changes" />
    </mtbwa:InvokeForReason>
  </Sequence>
</Activity>

特别是,我在第58行添加了ToolPath="C:\Program Files (x86)\MSBuild\12.0\Bin\"

TFSBuild.proj

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

  <Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\TeamBuild\Microsoft.TeamFoundation.Build.targets" />
  <Import Project="$(MSBuildExtensionsPath)\Microsoft\SDC\Microsoft.Sdc.Common.tasks" />
  <Import Project="$(MSBuildExtensionsPath)\ExtensionPack\MSBuild.ExtensionPack.tasks"/>

  <ProjectExtensions>
    <!-- Team Foundation Build Version - DO NOT CHANGE -->
    <ProjectFileVersion>2</ProjectFileVersion>
  </ProjectExtensions>

  <PropertyGroup>
    <RunCodeAnalysis>Never</RunCodeAnalysis>
    <UpdateAssociatedWorkItems>false</UpdateAssociatedWorkItems>
    <AdditionalVCOverrides></AdditionalVCOverrides>
    <CustomPropertiesForClean></CustomPropertiesForClean>
    <CustomPropertiesForBuild></CustomPropertiesForBuild>
    <SkipGetChangesetsAndUpdateWorkItems>False</SkipGetChangesetsAndUpdateWorkItems>
    <SkipWorkItemCreation>true</SkipWorkItemCreation>
    <BuildConfigurationsInParallel>true</BuildConfigurationsInParallel>
    <SkipDropBuild>false</SkipDropBuild>
  </PropertyGroup>

  <ItemGroup>
      <SolutionToBuild Include="$(BuildProjectFolderPath)/SolutionsToBuild/Common.sln">
      <Targets></Targets>
      <Properties></Properties>
    </SolutionToBuild>
  </ItemGroup>
  <ItemGroup>
    <ConfigurationToBuild Include="Release|Any CPU">
      <FlavorToBuild>Release</FlavorToBuild>
      <PlatformToBuild>Any CPU</PlatformToBuild>
    </ConfigurationToBuild>
  </ItemGroup>


  <PropertyGroup>
    <SkipClean>false</SkipClean>
    <SkipInitializeWorkspace>true</SkipInitializeWorkspace>
    <ForceGet>true</ForceGet>
    <IncrementalBuild>false</IncrementalBuild>
  </PropertyGroup>
</Project>

更新

我认为这可能与运行私有版本(Latest + Shelveset)有关。当我运行正常构建时,BuildNumber变量为MyBuild-Testing_20170328.1。这似乎工作正常。

1 个答案:

答案 0 :(得分:0)

此问题是由于私有和公共版本之间的差异造成的。使用Public Builds,构建立即编号为BuildName_DateFormat.BuildNumber。但是,私有构建只是数字(例如上面的57902)。

扩展程序中的代码执行以下操作:

string buildstring = this.TfsBuildNumber.Replace(string.Concat(this.BuildName, "_"), 
                              string.Empty);
char[] chrArray = new char[] { '.' };
string[] buildParts = buildstring.Split(chrArray, StringSplitOptions.RemoveEmptyEntries);
DateTime t = new DateTime(Convert.ToInt32(buildParts[0].Substring(0, 4), 
                                            CultureInfo.CurrentCulture), 
                          Convert.ToInt32(buildParts[0].Substring(4, 2), 
                                            CultureInfo.CurrentCulture),
                          Convert.ToInt32(buildParts[0].Substring(6, 2), 
                                            CultureInfo.InvariantCulture));

您是否可以看到它在构建名称上的子字符串,假设它已被剥离到日期组件(20170328)。私有构建不是那么长,所以失败。

当作为公共构建运行时,此构建工作正常 - 基本上这意味着在升级发生之前,此定义上的私有构建不可用。