Как я могу получить TFS 2010 для сборки каждого проекта в отдельный каталог? - PullRequest
22 голосов
/ 07 мая 2010

В нашем проекте мы хотели бы, чтобы наша сборка TFS помещала каждый проект в отдельную папку в папке перетаскивания, вместо того, чтобы помещать все файлы в одну плоскую структуру. Чтобы проиллюстрировать это, мы хотели бы видеть что-то вроде этого:

DropFolder/
  Foo/
    foo.exe
  Bar/
    bar.dll
  Baz
    baz.dll

Это в основном тот же вопрос, который был задан здесь , но теперь, когда мы используем сборки на основе рабочих процессов, эти решения, похоже, не работают. Решение, использующее свойство CustomizableOutDir, выглядело так, как будто оно будет работать лучше для нас, но я не могу распознать это свойство. Я настроил наш рабочий процесс для передачи его в MSBuild в качестве аргумента командной строки (/ p: CustomizableOutDir = true), но, похоже, MSBuild просто игнорирует его и помещает выходные данные в OutDir, заданный рабочим процессом.

Я посмотрел журналы сборки и вижу, что свойства CustomizableOutDir и OutDir в аргументах командной строки устанавливаются как MSBuild. Мне все еще нужно передать OutDir, чтобы в конце я смог скопировать свои файлы в TeamBuildOutDir.

Есть идеи, почему мой параметр CustomizableOutDir не распознается или есть лучший способ добиться этого?

Ответы [ 9 ]

14 голосов
/ 07 мая 2010

Я нашел хороший способ сделать это. Оказывается, так как вы можете установить OutDir в любое удобное вам значение в рабочем процессе, если вы установите его в пустую строку, MSBuild будет вместо этого использовать выходной путь для конкретного проекта. Это позволяет нам быть более гибкими. Вот мое полное решение (основанное на рабочем процессе сборки по умолчанию):

В задаче «Выполнить MSBuild» установите OutDir в пустую строку. В этой же задаче установите для ваших CommandLineArguments что-то вроде следующего. Это позволит вам иметь ссылку на OutDir TFS по умолчанию из вашего проекта:

String.Format("/p:CommonOutputPath=""{0}\\""", outputDirectory)

В каждом проекте, который вы хотите скопировать в папку удаления, установите OutputPath так:

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

Проверьте все, и у вас должна быть рабочая сборка, которая развертывает каждый из ваших проектов в свою папку в папке drop.

8 голосов
/ 23 ноября 2011

Я тоже решил эту проблему и думаю, что она чище, чем существующие решения в этой теме.

  • До действия Run MSBuild for Project я добавил действие Assign: projectName = Regex.Replace(New FileInfo(localProject).Name, "\.sln$", "").
  • Далее я добавил Create Directory активность: outputDirectory + "\" + projectName
  • Наконец, в упражнении MSBuild я изменил OutDir на outputDirectory + "\" + projectName.

Шаблон уже заполняет localProject полным путем к файлу .sln, который создается на Агенте, например, c:\build\path\to\MySolution.sln. Операция присвоения обрезает путь и расширение, помещая вывод в MySolution. Вам нужно будет создать переменную projectName и импортировать System.Text.RegularExpressions и System.IO.

Преимущество по сравнению с решением OP состоит в том, что вам не нужно редактировать каждый .csproj, эта информация выводится из имени файла решения.

4 голосов
/ 29 июля 2010

Мы должны были сделать это, чтобы обойти проблему, когда у нас есть Silverlight и библиотека .Net с одинаковым именем для сериализации CSLA. Библиотека будет перезаписана, и наши тесты не пройдут.

Я использовал ответ Джонатана и пост Джима Лэмба , но я обнаружил, что вам также нужно установить OutDir пустым.

Итак, вам нужно выполнить эти параметры для действий MSBuild (если вы используете следующий макрос, вам также нужно установить параметры действий для Clean, иначе вы получите предупреждение о том, что OutputPath не установлен):

  • Установите для CommandLineArguments значение String.Format("/p:SkipInvalidConfigurations=true;TeamBuildOutDir=""{0}"" {1}", BinariesDirectory, MSBuildArguments)
  • Установить OutDir пустым (был BinariesDirectory)

Я также создал макрос, который вы можете запустить в Visual Studio, который удаляет OutputPath из конфигураций и добавляет PropertyGroup, который содержит OutputPath для всех конфигов, например:

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

Вот макрос:

Public Sub SetTeamBuildOutDir()

    Dim projectObjects = DTE.Solution.Projects

    For Each project In projectObjects

        If project.ProjectItems IsNot Nothing Then
            SetTeamBuildOutDirRecursive(project)
        End If
    Next

End Sub

Sub SetTeamBuildOutDirRecursive(ByVal proj As Project)
    If proj.ConfigurationManager Is Nothing Then
        For Each subProj As ProjectItem In proj.ProjectItems
            If subProj.SubProject IsNot Nothing Then
                SetTeamBuildOutDirRecursive(subProj.SubProject)
            End If
        Next
    Else
        SetTeamBuildOutDir(proj)
    End If

End Sub

Sub SetTeamBuildOutDir(ByVal project As Project)
    'Do not handle .vdproj
    If project.FullName.ToLower().EndsWith(".vdproj") Then
        Exit Sub
    End If

    Dim needToSave = False
    Dim msproject = ProjectRootElement.Open(project.FullName)
    Dim outputPathGroupExists = False
    Dim outputPropertyGroup As ProjectPropertyGroupElement = Nothing
    Dim lastConfigPropertyGroup As ProjectPropertyGroupElement = Nothing

    For Each propertyGroup In msproject.PropertyGroups

        If propertyGroup.Label = "OutputPathLabel" Then
            outputPathGroupExists = True
            outputPropertyGroup = propertyGroup
        End If

        If Not String.IsNullOrEmpty(propertyGroup.Condition) AndAlso _
            propertyGroup.Condition.TrimStart().StartsWith("'$(Configuration)") Then

            lastConfigPropertyGroup = propertyGroup
        End If

        'Remove the OutputPath from the configurations
        Dim outputPathElement As ProjectPropertyElement = Nothing
        For Each element As ProjectPropertyElement In propertyGroup.Children
            If element.Name = "OutputPath" Then
                outputPathElement = element
            End If
        Next
        If outputPathElement IsNot Nothing Then
            propertyGroup.RemoveChild(outputPathElement)
            needToSave = True
        End If
    Next

    'If we want to always remove the group and add it back (in case of modifications to the group)
    'If outputPathGroupExists Then
    '    msproject.RemoveChild(outputPropertyGroup)
    '    outputPathGroupExists = False
    'End If

    If Not outputPathGroupExists Then
        Dim propertyGroup = msproject.CreatePropertyGroupElement()
        propertyGroup.Label = "OutputPathLabel"
        'Need to insert the PropertyGroup before the CSharp targets are included
        msproject.InsertAfterChild(propertyGroup, lastConfigPropertyGroup)

        Dim isDbProject = project.FullName.ToLower().EndsWith(".dbproj")

        Dim outputEmpty = propertyGroup.AddProperty("OutputPath", IIf(Not isDbProject, "bin\$(Configuration)\", "sql\$(Configuration)\"))
        outputEmpty.Condition = "'$(TeamBuildOutDir)'=='' "

        Dim outputTeamBuild = propertyGroup.AddProperty("OutputPath", "$(TeamBuildOutDir)\$(SolutionName)\$(MSBuildProjectName)\$(Configuration)\")
        outputTeamBuild.Condition = "'$(TeamBuildOutDir)'!='' "

        needToSave = True
    End If

    If needToSave Then
        'checkout the project file with tfs
        Shell("C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE\tf.exe checkout " & project.FullName, , True)

        'Save the project file
        msproject.Save()
    End If
End Sub

Надеюсь, это поможет !!!

2 голосов
/ 30 августа 2011

Приведенные здесь шаги не требуют изменения файла проекта - http://lajak.wordpress.com/2011/05/07/customize-binaries-folder-in-tfs-team-build/

1 голос
/ 07 января 2014

Не уверен, что вы все еще можете заставить Team build 2010 использовать последнюю версию msbuild, но есть новое свойство / p: GenerateProjectSpecificOutputFolder = true, если указано, биты будут сброшены в $ (OutDir) \ $ (ProjectName) \ for каждый проект.

1 голос
/ 11 декабря 2012

Я установил пакет Опубликованные приложения из Nuget для каждого исполняемого файла в Моем решении, и он создал подпапки в папке _PublishedApplications для каждого проекта во время сборки.

1 голос
/ 01 августа 2012

Вот очень простое решение, которое не требует модификации исходных файлов или файлов проекта. При настройке определения сборки Process -> Projects to Build вместо указания файла .sln в проектах для сборки добавьте каждый проект (.csproj или .vbproj). Теперь внутри шага «Запуск MSBuild for Project» вашего рабочего процесса измените свойство OutDir на следующее:

outputDirectory + "/" + serverBuildProjectItem.Substring(serverBuildProjectItem.LastIndexOf("/"), serverBuildProjectItem.Length - serverBuildProjectItem.LastIndexOf("/")).Replace(".csproj", String.Empty)

Это поместит выходные данные сборки каждого проекта в подкаталог с именем проекта.

0 голосов
/ 25 августа 2012

Вот еще одно очень простое решение, которое не требует модификации исходных файлов или файлов проекта. При настройке определения сборки Process -> Projects to Build вместо указания файла .sln в проектах для сборки добавьте каждый проект (.csproj или .vbproj). Теперь внутри шага «Запуск MSBuild for Project» вашего рабочего процесса измените свойство OutDir на следующее:

OutputDirectory + "\" + System.IO.Path.GetFileNameWithoutExtension(serverBuildProjectItem)
0 голосов
/ 07 мая 2010

Я не играл с TFS / MSBuild, чтобы поместить выходные файлы в отдельные папки, поэтому не могу дать прямой ответ. Однако вот несколько советов, которые я не заметил в вашей ссылке:

  • Вы можете добавить шаги после сборки к проектам, которые копируют необходимые файлы в структуру «развертывания». (Это, конечно, также работает на машинах разработчиков, что может быть проблемой). Мы используем этот подход для наших библиотек, которые создаются и затем копируются в общую папку libs (binaries) для других проектов, на которую они могут ссылаться.

  • Вы можете добавить цель MSBuild, чтобы скопировать нужные файлы туда, куда вы хотите. Мы переопределили цели по умолчанию «копировать в папку», чтобы скопировать файлы в другую папку, скрыть их, подписать их цифровой подписью, встроить в установщик, подписать установщик цифровой подписью, а затем скопировать (и другие полезные вещи, такие как файлы карт обфускации) и список изменений с момента последней сборки в папку drop. В конечном итоге добавление вашей собственной цели после сборки дает вам максимальный контроль над тем, что и где находится. (С минусовой стороны, вам, возможно, придется вручную добавлять любые новые библиотеки dll или exe к цели копирования после сборки, что может вызвать раздражение)

...