如何让TFS 2010将每个项目构建到单独的目录中?

如何让TFS 2010将每个项目构建到单独的目录中?,tfs,msbuild,tfsbuild,Tfs,Msbuild,Tfsbuild,在我们的项目中,我们希望让我们的TFS构建将每个项目放到drop文件夹下自己的文件夹中,而不是将所有文件放到一个平面结构中。为了举例说明,我们希望看到如下内容: DropFolder/ Foo/ foo.exe Bar/ bar.dll Baz baz.dll 这基本上与我们所问的问题相同,但现在我们使用基于工作流的构建,这些解决方案似乎不起作用。使用CustomizelOutDir属性的解决方案看起来最适合我们,但我无法识别该属性。我自定义了我们的工作流,

在我们的项目中,我们希望让我们的TFS构建将每个项目放到drop文件夹下自己的文件夹中,而不是将所有文件放到一个平面结构中。为了举例说明,我们希望看到如下内容:

DropFolder/
  Foo/
    foo.exe
  Bar/
    bar.dll
  Baz
    baz.dll
这基本上与我们所问的问题相同,但现在我们使用基于工作流的构建,这些解决方案似乎不起作用。使用CustomizelOutDir属性的解决方案看起来最适合我们,但我无法识别该属性。我自定义了我们的工作流,将其作为命令行参数传递给MSBuild(/p:customableoutdir=true),但MSBuild似乎只是忽略了它,并将输出放入工作流给定的OutDir中

我查看了构建日志,可以看到CustomizedLeOutDir和OutDir属性都在命令行参数中设置为MSBuild。我仍然需要传入OutDir,以便在最后将文件复制到TeamBuildOutDir


你知道为什么我的CustomizedLeOutDir参数没有被识别,或者有更好的方法来实现这一点吗?

我没有尝试过让TFS/MSBuild将输出文件放在单独的文件夹中,因此无法直接给出答案。然而,以下是我在你的链接中没有发现的几个建议:

  • 您可以向将所需文件复制到“部署”结构的项目中添加生成后步骤。(这当然也会在开发人员的机器上运行,这可能是一个难题)。我们对我们的库使用这种方法,这些库被构建,然后复制到一个共享的libs(binaries)文件夹中,供其他项目引用

  • 您可以添加MSBuild目标以将所需文件复制到所需的位置。我们已经覆盖了默认的“复制到放置文件夹”目标,将文件复制到另一个文件夹,对其进行模糊处理,对其进行数字签名,将其构建到安装程序中,对安装程序进行数字签名,然后将其(以及其他有用的内容,如模糊映射文件)和自上次构建以来的更改列表复制到放置文件夹。最终,添加您自己的构建后目标可以让您最大限度地控制将什么放在哪里。(不利的一面是,您可能必须手动将任何新的DLL或EXE添加到生成后复制目标,这可能会让人恼火)


    • 我想出了一个好办法。事实证明,由于可以在工作流中将OutDir设置为所需的任何值,因此如果将其设置为空字符串,MSBuild将改为使用特定于项目的OutputPath。这让我们更加灵活。以下是我的整个解决方案(基于默认构建工作流):

      在运行MSBuild任务中,将OutDir设置为空字符串。在同一任务中,将CommandLineArguments设置为如下所示。这将允许您从项目中引用TFS默认OutDir:

      String.Format("/p:CommonOutputPath=""{0}\\""", outputDirectory)
      
      在每个要复制到drop文件夹的项目中,按如下方式设置OutputPath:

      <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
          <OutputPath Condition=" '$(CommonOutputPath)'=='' ">bin\Release\</OutputPath>
          <OutputPath Condition=" '$(CommonOutputPath)'!='' ">$(CommonOutputPath)YourProjectName\bin\Release\</OutputPath>
      </PropertyGroup>
      
      
      bin\Release\
      $(CommonOutputPath)YourProjectName\bin\Release\
      

      签入所有内容,您应该有一个工作版本,可以将您的每个项目部署到drop文件夹下自己的文件夹中。

      我们必须这样做,以绕过一个问题,即我们有一个Silverlight和一个用于CSLA序列化的同名.Net库。库将被覆盖,我们的测试将失败

      我使用了乔纳森的答案,但是我发现你也需要设置为空

      因此,您需要为MSBuild活动执行这些参数(如果使用以下宏,则还需要为Clean设置活动参数,否则会收到未设置OutputPath的警告):

      • 将CommandLineArguments设置为
        String.Format(“/p:skipinValidConfiguration=true;TeamBuildOutDir=”“{0}”“{1}”,二进制目录,MSBuildArguments)
      • 将OutDir设置为空(was二进制目录)
      我还创建了一个可以在visual studio中运行的宏,该宏从配置中删除OutputPath,并添加了一个PropertyGroup,其中包含所有配置的OutputPath,如下所示:

      <PropertyGroup Label="OutputPathLabel">
        <OutputPath Condition="'$(TeamBuildOutDir)'=='' ">bin\$(Configuration)\</OutputPath>
        <OutputPath Condition="'$(TeamBuildOutDir)'!='' ">$(TeamBuildOutDir)\$(SolutionName)\$(MSBuildProjectName)\$(Configuration)\</OutputPath>
      </PropertyGroup>
      

      希望这有帮助

      这里的步骤不需要修改项目文件-

      我也解决了这个问题,我认为它比这个线程上现有的解决方案更干净

      • 为Project运行MSBuild
        活动之前,我添加了一个
        Assign
        活动:
        projectName=Regex.Replace(新文件信息(localProject).Name,\.sln$,“”)
      • 接下来,我添加了一个
        Create Directory
        活动:
        outputDirectory+“\”+projectName
      • 最后,在MSBuild活动中,我将
        OutDir
        更改为
        outputDirectory+“\”+projectName
      模板已经用在代理上生成的
      .sln
      文件的完整路径名填充
      localProject
      ,例如
      c:\build\path\to\MySolution.sln
      。分配活动切断路径和扩展,将输出放在
      MySolution
      中。您需要创建
      projectName
      变量,并导入
      System.Text.RegularExpressions
      System.IO


      与OP的解决方案相比,它的优点是您不必编辑每个
      .csproj
      ,这些信息是从解决方案文件的名称推断出来的

      这里有一个非常简单的解决方案,它不需要修改源文件或项目文件。设置生成定义的过程->要生成的项目时,不要在要生成的项目中指定.sln文件,而是添加每个项目(.csproj或.vbproj)。现在,在工作流的“为项目运行MSBuild”步骤中,将OutDir属性更改为以下内容:

      outputDirectory + "/" + serverBuildProjectItem.Substring(serverBuildProjectItem.LastIndexOf("/"), serverBuildProjectItem.Length - serverBuildProjectItem.LastIndexOf("/")).Replace(".csproj", String.Empty)
      
      OutputDirectory + "\" + System.IO.Path.GetFileNameWithoutExtension(serverBuildProjectItem)
      

      这将把每个项目的生成输出放在以项目命名的子目录中。

      下面是另一个非常简单的解决方案,它不需要修改源文件或项目
      OutputDirectory + "\" + System.IO.Path.GetFileNameWithoutExtension(serverBuildProjectItem)