你可以在TFS上使用多个工作文件夹吗?

时间:2009-11-24 13:43:20

标签: tfs msbuild msbuild-buildengine

在工作区只有一个工作文件夹的项目中,我的构建脚本运行良好。现在我正在使用一个需要2个工作文件夹的新项目,我之前脚本的所有checkout和checkin命令都会失败,没有找到任何文件。

显然,我不理解这里工作区实现的关键部分......我有一个项目依赖于其他项目,第二个工作文件夹基本上是第三方文件夹,引用了各种已发布的编译我的项目所需的DLL和头文件。有2个活动文件夹,本地文件夹是:

$(SourceDir)\TEAM-MAIN\Address Finalizer
$(SourceDir)\TEAM-MAIN\HH-CAHPS Project\MAINLINE\3rd Party

构建的代码工作正常,但自定义AfterGet在以下条目上失败:

<!-- Check out all of the assemblyInfo files -->
<Exec Command="$(TfCommand) checkout AssemblyInfo.cs /recursive"
      WorkingDirectory="$(MSBuildProjectDirectory)\..\sources"
      ContinueOnError="false"/>

如果我有一个工作文件夹并将源移动到足够高的点来获取所有需要的文件,那么该项目当然会工作,但我不想通过43个其他项目来实现我想要的东西,让沿着装配文件捣乱...

我也尝试过:

<!-- Check out all of the assemblyInfo files -->
<Exec Command="$(TfCommand) checkout AssemblyInfo.cs /recursive"
      WorkingDirectory="$(SolutionRoot)"
      ContinueOnError="false"/>

同样的问题,无法找到任何程序集文件......我已经检查了构建日志,我肯定会在构建阶段检查出程序集文件...

Task "Get"
  Get TeamFoundationServerUrl="http://pgpd-team01:8080/" BuildUri="vstfs:///Build/Build/1430" Force=True Overwrite=False PopulateOutput=False Preview=False Recursive=True Version="C7564" Workspace="SBN01P-TFS03_61"
<snip>
  Getting C:\Users\tfsservice\AppData\Local\Temp\InfoTurn\Address Finalizer\Sources\Address Finalizer\Address Finalizer\Properties\AssemblyInfo.cs;C7525.

如果有人有任何想法或者可以指点我一些文章来更好地解释多个工作文件夹是如何工作的,我会很感激。

某些构建变量的值:

MSBuildProjectDirectory: C:\Users\tfsservice\AppData\Local\Temp\InfoTurn\Address Finalizer\BuildType

SolutionRoot: C:\Users\tfsservice\AppData\Local\Temp\InfoTurn\Address Finalizer\Sources

为了提供更多信息,我添加了以下命令:

    <!-- Report what our working folders are -->
    <Exec 
      Command='$(TfCommand) workfold'
      WorkingDirectory="$(SolutionRoot)\TEAM-MAIN\Address Finalizer"/>

结果是:

Task "Exec"
  Command:
  "C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\PrivateAssemblies\..\tf.exe" workfold
  ===============================================================================
  Workspace: SBN01P-TFS03_61 (tfsservice)
  Server   : http://pgpd-team01:8080/
   $/InfoTurn/TEAM-MAIN/Address Finalizer: C:\Users\tfsservice\AppData\Local\Temp\InfoTurn\Address Finalizer\Sources\TEAM-MAIN\Address Finalizer
   $/InfoTurn/TEAM-MAIN/HH-CAHPS Project/MAINLINE/3rd Party: C:\Users\tfsservice\AppData\Local\Temp\InfoTurn\Address Finalizer\Sources\TEAM-MAIN\HH-CAHPS Project\MAINLINE\3rd Party

我发现以下工作目录可以正常工作:

WorkingDirectory="$(SolutionRoot)\TEAM-MAIN\Address Finalizer"

但是以下两个没有,请注意第二个是我的第二个工作文件夹:

WorkingDirectory="$(SolutionRoot)"
WorkingDirectory="$(SolutionRoot)\TEAM-MAIN\HH-CAHPS Project\MAINLINE\3rd Party"

我为标签任务获得的错误是最有用的:

Using "Label" task from assembly "C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\PrivateAssemblies\Microsoft.TeamFoundation.Build.Tasks.VersionControl.dll".
Task "Label"
  Label TeamFoundationServerUrl="http://pgpd-team01:8080/" BuildUri="vstfs:///Build/Build/1507" Name="Address Finalizer 2.0.1 Build 039" Recursive=True Comments="Automated build: Address Finalizer 2.0.1 Build 039" Version="W" Child="replace" Files="C:\Users\tfsservice\AppData\Local\Temp\InfoTurn\Address Finalizer\Sources"
C:\Users\tfsservice\AppData\Local\Temp\InfoTurn\Address Finalizer\BuildType\TFSBuild.proj(310,5,310,5): error : Error: Unable to determine the workspace.

结账的实际错误是无效的:

Task "Exec"
  Command:
  "C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\PrivateAssemblies\..\tf.exe" checkout AssemblyInfo.cs /recursive
  No matching items found in C:\Users\tfsservice\AppData\Local\Temp\InfoTurn\Address Finalizer\Sources\AssemblyInfo.cs in your workspace.
C:\Users\tfsservice\AppData\Local\Temp\InfoTurn\Address Finalizer\BuildType\TFSBuild.proj(280,5): error MSB3073: The command ""C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\PrivateAssemblies\..\tf.exe" checkout AssemblyInfo.cs /recursive" exited with code 1.

2 个答案:

答案 0 :(得分:2)

答案 1 :(得分:1)

我的脚本现在正在运行,有几个小问题导致了问题。一个是,对于许多命令,您必须引用确切的工作目录(本地文件夹)才能使命令起作用。另一个问题是需要将属性设置移动到自定义任务中,以便其他任务可以正确使用它们。所以希望我的完整构建脚本包括下面将帮助其他人。在任何编辑器中粘贴它都会使它更容易阅读。

  <!-- Generate all of the project specific variables we will need for versioning -->
  <PropertyGroup>
    <VersioningFile>$(SolutionRoot)\TEAM-MAIN\Address Finalizer\Address Finalizer\versionNumber.txt</VersioningFile>
    <TfCommand>"$(TeamBuildRefPath)\..\tf.exe"</TfCommand>
    <WorkingDirectory>$(SolutionRoot)\TEAM-MAIN\Address Finalizer</WorkingDirectory>
    <WorkingDirectory2>$(SolutionRoot)\TEAM-MAIN\HH-CAHPS Project\MAINLINE\3rd Party</WorkingDirectory2>
    <DllName>Address_Finalizer.dll</DllName>
    <PublishedFolder>$(SolutionRoot)\TEAM-MAIN\HH-CAHPS Project\MAINLINE\3rd Party\bin\PG File Import</PublishedFolder>
    <LabelPath>unknown</LabelPath>
  </PropertyGroup>

  <!-- Only edit the properties when usign this as a template for other builds -->

  <Import Project="$(MSBuildExtensionsPath)\ExtensionPack\MSBuild.ExtensionPack.tasks"/>
  <Import Project="$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets"/>

  <Target Name="AfterGet">   
    <Message Text="FOOBAR Version File: $(VersioningFile)" />
    <Message Text="FOOBAR Working Dir : $(WorkingDirectory)" />

    <!-- Report what our working folders are -->
    <Exec
      Command='$(TfCommand) workfold'
      WorkingDirectory="$(WorkingDirectory)"/>

    <!-- Generate the version # -->
    <CallTarget Targets="GenerateVersion"/>

    <!-- Version the assemblies -->
    <CallTarget Targets="VersionAssemblies"/>      

    <!-- Configure the deployment for QA -->
    <CallTarget Targets="ConfigureForQA"/>

    <!-- Apply a label to everything -->
    <CallTarget Targets="LabelWorkingDirectory"/>
    <CallTarget Targets="LabelWorkingDirectory2"/>
  </Target>

  <Target Name="AfterDropBuild">
    <!-- Generate all of the project specific variables we will need for deployment, dependant on versioning -->
    <PropertyGroup>
      <ReleaseDLL>$(DropLocation)\$(BuildNumber)\Release\$(DllName)</ReleaseDLL>
      <PublishedDLL>$(PublishedFolder)\$(DllName)</PublishedDLL>
    </PropertyGroup>

    <!-- Check out the published DLL -->
    <Exec 
      Command='$(TfCommand) checkout /lock:checkout "$(PublishedDLL)"'
      WorkingDirectory="$(WorkingDirectory)" />

    <!-- Copy release to published -->
    <Copy 
      SourceFiles="$(ReleaseDLL)" 
      DestinationFolder="$(PublishedFolder)"/>

    <!-- Check in the published DLL -->
    <Exec 
      Command='$(TfCommand) checkin /override:Automated /noprompt /comment:"$(VersionComment)" "$(PublishedDLL)"'
      WorkingDirectory="$(WorkingDirectory)" />
  </Target>

  <Target Name="GenerateVersion">
    <!-- Check out the version file -->
    <Exec
      Command='$(TfCommand) checkout /lock:checkout "$(VersioningFile)"'
      WorkingDirectory="$(SolutionRoot)"/>

    <!-- Increment the revision # in the file and save it -->
    <Version VersionFile="$(VersioningFile)" BuildType="None" RevisionType="Increment">
      <Output TaskParameter="Major" PropertyName="Major" />
      <Output TaskParameter="Minor" PropertyName="Minor" />
      <Output TaskParameter="Build" PropertyName="Build" />
      <Output TaskParameter="Revision" PropertyName="Revision" />
    </Version>

    <!-- Pad the revision out to 3 digits. -->
    <PropertyGroup>
      <PaddedRevision Condition="$(Revision) < 1000">$(Revision)</PaddedRevision>
      <PaddedRevision Condition="$(Revision) < 100">0$(Revision)</PaddedRevision>
      <PaddedRevision Condition="$(Revision) < 10">00$(Revision)</PaddedRevision>
    </PropertyGroup>

    <!-- Generate what our version string looks like for the logfile -->
    <CreateProperty Value="Address Finalizer $(Major).$(Minor).$(Build) Build $(PaddedRevision)">
      <Output TaskParameter="Value" PropertyName="ProjectVersion" />
    </CreateProperty>

    <CreateProperty Value="Automated build: $(ProjectVersion)">
      <Output TaskParameter="Value" PropertyName="VersionComment" />
    </CreateProperty>

    <Message Text="New Version is: $(ProjectVersion)"/>

    <!-- Check in the version file -->
    <Exec
      Command='$(TfCommand) checkin /noprompt /comment:"$(VersionComment)" "$(VersioningFile)"'
      WorkingDirectory="$(SolutionRoot)"/>
  </Target>

  <Target Name="VersionAssemblies">
    <!-- Get all of the assemblyinfo files from all of the directories (should only be one) -->
    <ItemGroup>
      <AssemblyInfoList Include="$(SolutionRoot)\**\assemblyinfo.cs"/>
    </ItemGroup>

    <Message Text="FOOBAR Build Dir    : $(MSBuildProjectDirectory)"/>
    <Message Text="FOOBAR Solution Root: $(SolutionRoot)"/>
    <Message Text="FOOBAR Working Dir  : $(WorkingDirectory)"/>

    <!-- Check out all of the assemblyInfo files -->
    <Exec 
      Command="$(TfCommand) checkout AssemblyInfo.cs /recursive"
      WorkingDirectory="$(WorkingDirectory)"
      ContinueOnError="false"/>

    <!-- Change the version # on all of the assemblyInfo files -->
    <MSBuild.ExtensionPack.Framework.AssemblyInfo AssemblyFileVersion="$(Major).$(Minor).$(Build).$(Revision)" AssemblyInfoFiles="@(AssemblyInfoList)"/>
    <MSBuild.ExtensionPack.Framework.AssemblyInfo AssemblyVersion="$(Major).$(Minor).$(Build).$(Revision)" AssemblyInfoFiles="@(AssemblyInfoList)"/>

    <!-- Check in all of the assemblyInfo files -->
    <Exec 
      Command='$(TfCommand) checkin /override:Automated /comment:"$(VersionComment)" /noprompt AssemblyInfo.cs /recursive'
      WorkingDirectory="$(WorkingDirectory)"
      ContinueOnError="false"/> 
  </Target>

  <Target Name="ConfigureForQA">
    <!-- Grab all of the QA app.config files (should only be one) -->
    <CreateItem Include="$(SolutionRoot)\**\app-qa.config">
      <Output TaskParameter ="Include" ItemName ="AppConfigFiles"/>
    </CreateItem>

    <!-- Copy the QA app.config to app.config to make it the driving config file -->
    <Copy
      SourceFiles="@(AppConfigFiles)"
      OverwriteReadOnlyFiles="True"
      DestinationFiles="@(AppConfigFiles->'$(SolutionRoot)\%(RecursiveDir)app%(Extension)')"/>
  </Target>

  <Target Name="LabelWorkingDirectory">
    <Message Text="FOOBAR Version: $(ProjectVersion)" />
    <Message Text="FOOBAR Comment: $(VersionComment)" />
    <Message Text="FOOBAR Path   : $(LabelPath)" />

    <!-- Apply Label on workspace -->
    <Label
      TeamFoundationServerUrl="$(TeamFoundationServerUrl)"
      BuildUri="$(BuildUri)"
      Name="$(ProjectVersion)"
      Files="$(WorkingDirectory)"
      Comments="$(VersionComment)"
      ContinueOnError="False"
      Recursive="True" />
  </Target>

  <Target Name="LabelWorkingDirectory2">
    <Message Text="FOOBAR Version: $(ProjectVersion)" />
    <Message Text="FOOBAR Comment: $(VersionComment)" />
    <Message Text="FOOBAR Path   : $(LabelPath)" />

    <!-- Apply Label on workspace -->
    <Label
      TeamFoundationServerUrl="$(TeamFoundationServerUrl)"
      BuildUri="$(BuildUri)"
      Name="$(ProjectVersion)"
      Files="$(WorkingDirectory2)"
      Comments="$(VersionComment)"
      ContinueOnError="False"
      Recursive="True" />
  </Target>