Скопируйте один файл в целевой каталог при развертывании из командных служб Visual Studio.

Я использую VSTS в качестве сервера сборки, и при сборке я хочу скопировать содержимое папки bin в корень цели, а также пользовательские файлы из другой папки в эту цель. MSDN предлагает использовать шаблон мини-соответствия , но копирует файлы со структурой подкаталогов. Я не заинтересован в восстановлении структуры.

Например, я получаю эту структуру папок:

Project
    MyProjectFiles
    bin
        x86 (it's build configuration)
            Project.exe
    Other project files
    Project.sln
SomeScrips
    script1.ps1

Но я хочу получить эту структуру папок:

Project.exe
SomeScripts
    script.ps1

Какой шаблон мини-соответствия я могу использовать для своих требований?


person Georgy Grigoryev    schedule 04.01.2016    source источник
comment
Вы используете XAML или новую веб-систему сборки?   -  person Pascal Berger    schedule 04.01.2016
comment
новая веб-система   -  person Georgy Grigoryev    schedule 04.01.2016
comment
Ни один из ответов не учитывает нетривиальные сценарии (более одного проекта), за исключением, может быть, ответа DotBerts. Обработка файлов и папок в сборках vNext, возможно, хуже, чем XAML, особенно когда вы хотите получить артефакт из $(build.sources)\setup\MyInstaller\bin\Release\myinstaller.msi, скопированный в папку $(build.artifactstaging) (не $(build.artifactstaging)\setup\MyInstaller\bin\Release)   -  person StingyJack    schedule 25.07.2017


Ответы (7)


С новой веб-системой сборки вы можете использовать несколько шаблонов за один шаг. Поэтому вы можете сделать что-то вроде этого для вашего случая:

Project\bin\x86\Release\project.exe
SomeScripts\**\*

Или, если у вас есть платформа сборки и конфигурация в переменной (например, BuildPlatform/BuildConfiguration), которую вы также используете на этапе сборки, вы можете использовать их в шаблоне:

Project\bin\$(BuildPlatform)\$(BuildConfiguration)\project.exe
SomeScripts\**\*

Если вы хотите, чтобы project.exe было в корне, а не в структуре, вам нужно использовать Copy Task, чтобы сначала разместить ваши файлы в желаемой структуре. Вы можете использовать $(Build.StagingDirectory) в качестве цели для этого. После этого используйте задачу «Публикация» с $(Build.StagingDirectory) в качестве корня копирования и опубликуйте все из этого корня в папку.

person Pascal Berger    schedule 04.01.2016
comment
Нет, это не работает, как ожидалось. если я сделаю так, я получу следующую структуру каталогов: Project\bin\x86\Release\project.exe Project\obj\x86\Release\project.exe Project\bin\Release\project.exe Project\obj\Release \проект.exe - person Georgy Grigoryev; 04.01.2016
comment
но мне нужен только Project\bin\x86\Release\project.exe - person Georgy Grigoryev; 04.01.2016
comment
Нет, он по-прежнему копирует структуру папок - person Georgy Grigoryev; 04.01.2016
comment
Обновлен ответ, как реструктурировать файлы - person Pascal Berger; 05.01.2016
comment
Даже если вы используете $(Build.StagingDirectory), вы не можете использовать описанные здесь шаблоны. - person Daniel Bişar; 22.01.2016
comment
Почему нет? Смотрите ответ Эдди с подробными скринами как выставить параметры - person Pascal Berger; 22.01.2016
comment
Проблема в исходной папке. Как Эдди описал выше, вам нужно будет установить исходную папку в фактический проект или даже в двоичную папку. Оттуда вы выполняете матч. Вы сказали, что мини-соответствие, такое как Project\bin\$(BuildPlatform)\$(BuildConfiguration)\project.exe и SomeScripts\**\*, даст желаемый результат. Но это не так. Независимо от того, используете ли вы промежуточный каталог или нет. Это тот самый Георгий, о котором упоминал. - person Daniel Bişar; 22.01.2016
comment
Возможно, ответ был недостаточно ясен. Приведенные выше шаблоны мини-матчей копируют структуру. Для изменения структуры вам нужна задача копирования с различными шаблонами мини-соответствия, как описано Эдди выше. - person Pascal Berger; 22.01.2016

Вам нужно указать корень копии, если вы хотите копировать файлы только без структуры папок. Поскольку файл project.exe находится по другому пути с файлом script.ps1, вам необходимо скопировать их в другую задачу копирования.

Выполните следующие действия:

  1. Добавьте шаг «Копировать файлы», чтобы скопировать «project.exe». Настройки, подобные следующим: введите здесь описание изображения
  2. Добавьте шаг «Копировать файлы», чтобы скопировать папку «SomeScripts». Настройки, подобные следующим: введите здесь описание изображения
  3. Добавьте шаг «Копировать и опубликовать артефакты сборки», чтобы скопировать эти файлы в «удаление». Настройки, подобные следующим: введите здесь описание изображения

Теперь вы должны получить в папке drop следующее:

Project.exe
SomeScripts
    script.ps1
person Eddie Chen - MSFT    schedule 05.01.2016
comment
Похоже, это именно то, что я хочу сделать, поэтому я голосую, но у нас нет шага копирования файлов, доступного в нашем локальном экземпляре сборки TFS. Является ли это еще одним примером того, как MS решила нанести ущерб локальной установке без уважительной причины? Это довольно базовая функциональность, которую можно пропустить. Плохое шоу MS, плохое шоу. - person Steve Pettifer; 09.03.2016
comment
@StevePettifer Извините за неудобства. По сравнению с локальной TFS, VSTS является онлайн-сервисом и использует другую модель выпуска, обновления и исправления могут поставляться непрерывно. Таким образом, задачи сборки продолжают расти. Вот почему вы не видели некоторые задачи в TFS. Эти задачи теперь доступны в TFS2015 Update2 RC2: visualstudio.com/ en-us/news/tfs2015-update2-vs.aspx. Кстати, все задачи VSTS размещены на GitHub, вы можете скачать их и загрузить на свой TFS Server. См. эту ссылку github.com/Microsoft/vso-agent-tasks и это: github.com/Microsoft/tfs-cli - person Eddie Chen - MSFT; 10.03.2016
comment
Спасибо, это приятно знать. К сожалению, я не могу повлиять на обновление TFS (мы достаточно большие и бюрократические, чтобы иметь выделенных администраторов TFS/ALM и корпоративную инерцию, как вы не поверите), но получение самих задач может быть ходячим - не смог найти их. В основном мы использовали сценарии msbuild, чтобы обойти такие проблемы. Немного неискренне предполагать, что у вас не может быть тех же вариантов использования ci и cd для локальной среды, что и VS Online (хотя мне нравится VSO и я использую его для других моих клиентских проектов). - person Steve Pettifer; 10.03.2016
comment
Да, у нас тоже нет только копирования файлов. Есть файлы копирования машины Windows, для которых требуется настроить сервер в качестве цели развертывания, и файлы копирования Azure, для которых, конечно же, требуется Azure. - person Chaim Eliyah; 27.05.2016
comment
Каждый вечер перед тем, как лечь спать, я вытаскиваю маленькую статуэтку билла со своей тумбочки и безмолвно молюсь, чтобы кто-нибудь добавил опцию сглаживания иерархии в действие «Копировать файлы». Такой вариант восстановил бы здравомыслие в моем мире. AFAICT Теперь я вынужден прибегать к PowerShell для копирования файлов. CopyFiles выглядит незаконченным как есть. - person 9Rune5; 07.06.2016
comment
@ 9Rune5 Наконец-то появились новые агенты сборки, которые поставляются с обновлением 1 TFS 2017. Спасибо за восстановление моей веры. - person JamesQMurphy; 15.09.2017

Параметр «Свести папки» в разделе «Дополнительно» шага «Копировать файлы».

Если вы используете TFS Online (Visual Studio Online) и вам не нужно копировать структуру папок, используйте параметр «Свести папки» в разделе «Дополнительно» шага «Копировать файлы» в определении сборки.

person igor_1024    schedule 11.02.2017
comment
пожалуйста, предоставьте подробности с вашим ответом. - person Sachith Muhandiram; 11.02.2017
comment
Если вы используете TFS Online (Visual Studio Online) и вам не нужно копировать структуру папок, используйте параметр «Свести папки» в разделе «Дополнительно» шага «Копировать файлы» в определении сборки. - person igor_1024; 12.02.2017
comment
Теперь это доступно в локальной версии TFS 2017, обновление 1. Раздел «Дополнительно» был свернут, и я даже не видел его сначала. Но о чудо, там были файлы Flatten. - person JamesQMurphy; 15.09.2017
comment
Честно говоря, почему одна из самых простых команд в любой ОС сделана такой сложной? Официальная документация также бесполезна с несколькими примерами, если они вообще есть. Параметр flatten не объясняет, что он сглаживает и как. Microsoft действительно нужно действовать сообща. - person ATL_DEV; 02.03.2021

Для тех, кто хотел бы иметь сценарий PowerShell для использования на вашем сервере сборки, вот рабочий (по крайней мере, на моем сервере сборки;)) пример:

param
(
    [string] $buildConfiguration = "Debug",
    [string] $outputFolder = $PSScriptRoot + "\[BuildOutput]\"
)

Write-Output "Copying all build output to folder '$outputFolder'..."

$includeWildcards = @("*.dll","*.exe","*.pdb","*.sql")
$excludeWildcards = @("*.vshost.*")

# create target folder if not existing, or, delete all files if existing
if(-not (Test-Path -LiteralPath $outputFolder)) {
    New-Item -ItemType Directory -Force -Path $outputFolder | Out-Null

    # exit if target folder (still) does not exist
    if(-not (Test-Path -LiteralPath $outputFolder)) {
        Write-Error "Output folder '$outputFolder' could not be created."
        Exit 1
    }
} else {
    Get-ChildItem -LiteralPath $outputFolder -Include * -Recurse -File | foreach {
        $_.Delete()
    }
    Get-ChildItem -LiteralPath $outputFolder -Include * -Recurse -Directory | foreach {
        $_.Delete()
    }
}

# find all output files (only when in their own project directory)
$files = @(Get-ChildItem ".\" -Include $includeWildcards -Recurse -File |
    Where-Object {(
        $_.DirectoryName -inotmatch '\\obj\\' -and
        $_.DirectoryName -inotmatch '\\*Test*\\' -and
        $_.DirectoryName -ilike "*\" + $_.BaseName + "\*" -and
        $_.DirectoryName -ilike "*\" + $buildConfiguration
    )}
)

# copy output files (overwrite if destination already exists)
foreach ($file in $files) {
    Write-Output ("Copying: " + $file.FullName)
    Copy-Item $file.FullName $outputFolder -Force

    # copy all dependencies from folder (also in subfolders) to output folder as well (if not existing already)
    $dependencies = Get-ChildItem $file.DirectoryName -Include $includeWildcards -Exclude $excludeWildcards -Recurse -File
    foreach ($dependency in $dependencies) {
        $dependencyRelativePathAndFilename = $dependency.FullName.Replace($file.DirectoryName, "")
        $destinationFileName = Join-Path -Path $outputFolder -ChildPath $dependencyRelativePathAndFilename
        if (-not(Test-Path -LiteralPath $destinationFileName)) {
            Write-Output ("Copying: " + $dependencyRelativePathAndFilename + " => " + $destinationFileName)

            # create sub directory if not exists
            $destinationDirectory = Split-Path $destinationFileName -Parent
            if (-not(Test-Path -LiteralPath $destinationDirectory)) {
                New-Item -Type Directory $destinationDirectory
            }
            Copy-Item $dependency.FullName $destinationDirectory
        } else {
            Write-Debug ("Ignoring (existing destination): " + $dependency.FullName)
        }
    }
}

Вот сценарий, используемый на этапе сборки PowerShell:

Сборка TFS 2015 – шаг вывода в одну папку

person DotBert    schedule 17.06.2016
comment
Вы знаете, что значит KISS?) Я думаю, что пару шагов проще, чем поддержка этого скрипта - person Georgy Grigoryev; 17.06.2016
comment
Я знаю @GeorgyGrigoryev - это всегда нужно учитывать. Этот делает одну работу и делает ее хорошо, имхо. Пожалуйста, не стесняйтесь разделять файл на что угодно, или, что еще лучше, поделитесь своим решением;)... - person DotBert; 30.06.2016
comment
Да, но я остановился на том, что должен сделать свой скрипт развертывания со структурой папок и избавился от этой проблемы. Мое решение использует один из ответов выше. - person Georgy Grigoryev; 02.07.2016

В TFS2017update1 и более поздних версиях, VSTS, вы можете просто установить флажок Свести папки в разделе "Дополнительно" в Задача копирования файлов. Самое простое решение на данный момент.

введите здесь описание изображения

Это сгладит структуру папок и скопирует все файлы в указанную целевую папку.

person PatrickLu-MSFT    schedule 15.09.2017

Параметр «flattenFolders» также доступен в качестве параметра задачи YAML. В следующем фрагменте кода показана задача CopyFiles@2, которая копирует выходные данные сборки в $(Build.ArtifactStagingDirectory). Когда я указываю параметр flattenFolders: true, структура вложенных папок bin\release\...\My.exe сглаживается, что означает, что исполняемые файлы копируются в корень $(Build.ArtifactStagingDirectory).

- task: CopyFiles@2
  displayName: 'Copy Files to: $(Build.ArtifactStagingDirectory)'
  inputs:
    SourceFolder: '$(system.defaultworkingdirectory)'
    Contents: |
     **\bin\$(BuildConfiguration)\**\*.exe
    TargetFolder: '$(Build.ArtifactStagingDirectory)'
    flattenFolders: true

Дополнительную документацию по задаче CopyFiles можно найти здесь: https://docs.microsoft.com/en-us/azure/devops/pipelines/tasks/utility/copy-files?view=vsts&tabs=yaml

person thomasgalliker    schedule 16.01.2019

Сделайте артефакты каждого файла, который вы хотите скопировать. Затем создайте задачу «копировать файл» для каждого файла этих артефактов. Тогда он не копирует исходную древовидную структуру.

person backyard hack mechanic    schedule 09.01.2017