Скопируйте все файлы и папки, используя msbuild
Просто интересно, может ли кто-нибудь помочь мне с некоторыми сценариями msbuild, которые я пытаюсь написать. Я хотел бы скопировать все файлы и подпапки из одной папки в другую, используя msbuild.
{ProjectName}
|----->Source
|----->Tools
|----->Viewer
|-----{about 5 sub dirs}
Что мне нужно сделать, это скопировать все файлы и подпапки из папки инструментов в папку отладки для приложения. Это код, который у меня есть до сих пор.
<ItemGroup>
<Viewer Include="..\$(ApplicationDirectory)\Tools\viewer\**\*.*" />
</ItemGroup>
<Target Name="BeforeBuild">
<Copy SourceFiles="@(Viewer)" DestinationFolder="@(Viewer->'$(OutputPath)\\Tools')" />
</Target>
Сценарий сборки запускается, но не копирует файлы или папки.
Спасибо
11 ответов
Я тоже искал помощи по этому вопросу. Это заняло у меня некоторое время, но вот что я сделал, это сработало очень хорошо.
<Target Name="AfterBuild">
<ItemGroup>
<ANTLR Include="..\Data\antlrcs\**\*.*" />
</ItemGroup>
<Copy SourceFiles="@(ANTLR)" DestinationFolder="$(TargetDir)\%(RecursiveDir)" SkipUnchangedFiles="true" />
</Target>
Это рекурсивно скопировало содержимое папки с именем antlrcs
к $(TargetDir)
,
Я думаю, что проблема может быть в том, как вы создаете свою ItemGroup и вызываете задачу копирования. Посмотрите, имеет ли это смысл:
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
<PropertyGroup>
<YourDestinationDirectory>..\SomeDestinationDirectory</YourDestinationDirectory>
<YourSourceDirectory>..\SomeSourceDirectory</YourSourceDirectory>
</PropertyGroup>
<Target Name="BeforeBuild">
<CreateItem Include="$(YourSourceDirectory)\**\*.*">
<Output TaskParameter="Include" ItemName="YourFilesToCopy" />
</CreateItem>
<Copy SourceFiles="@(YourFilesToCopy)"
DestinationFiles="@(YourFilesToCopy->'$(YourDestinationDirectory)\%(RecursiveDir)%(Filename)%(Extension)')" />
</Target>
</Project>
Я немного новичок в MSBuild, но нахожу задачу EXEC удобной для подобных ситуаций. Я столкнулся с той же проблемой в своем проекте, и это сработало для меня и было намного проще. Кто-то, пожалуйста, дайте мне знать, если это не хорошая практика.
<Target Name="CopyToDeployFolder" DependsOnTargets="CompileWebSite">
<Exec Command="xcopy.exe $(OutputDirectory) $(DeploymentDirectory) /e" WorkingDirectory="C:\Windows\" />
</Target>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
<PropertyGroup>
<YourDestinationDirectory>..\SomeDestinationDirectory</YourDestinationDirectory>
<YourSourceDirectory>..\SomeSourceDirectory</YourSourceDirectory>
</PropertyGroup>
<Target Name="BeforeBuild">
<CreateItem Include="$(YourSourceDirectory)\**\*.*">
<Output TaskParameter="Include" ItemName="YourFilesToCopy" />
</CreateItem>
<Copy SourceFiles="@(YourFilesToCopy)"
DestinationFiles="$(YourFilesToCopy)\%(RecursiveDir)" />
</Target>
</Project>
\**\*.*
помогите получить файлы со всей папки.
RecursiveDir поможет поместить все файлы в соответствующую папку...
Вот пример, который работал:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<MySourceFiles Include="c:\MySourceTree\**\*.*"/>
</ItemGroup>
<Target Name="CopyFiles">
<Copy
SourceFiles="@(MySourceFiles)"
DestinationFiles="@(MySourceFiles->'c:\MyDestinationTree\%(RecursiveDir)%(Filename)%(Extension)')"
/>
</Target>
</Project>
источник: https://msdn.microsoft.com/en-us/library/3e54c37h.aspx
Это задача копирования, которую я использовал в своем собственном проекте, она отлично работала для меня, которая успешно копирует папку с подпапками в место назначения:
<ItemGroup >
<MyProjectSource Include="$(OutputRoot)/MySource/**/*.*" />
</ItemGroup>
<Target Name="AfterCopy" AfterTargets="WebPublish">
<Copy SourceFiles="@(MyProjectSource)"
OverwriteReadOnlyFiles="true" DestinationFolder="$(PublishFolder)api/% (RecursiveDir)"/>
В моем случае я скопировал папку публикации проекта в другую папку назначения, я думаю, что это похоже на ваш случай.
Вы пытались указать конкретный каталог назначения вместо
DestinationFolder="@(Viewer->'$(OutputPath)\\Tools')" ?
Я не очень опытный с продвинутым синтаксисом MSBuild, но
@(Viewer->'$(OutputPath)\\Tools')
выглядит странно для меня. Сценарий выглядит хорошо, поэтому проблема может быть в значениях $(ApplicationDirectory)
а также $(OutputPath)
РЕДАКТИРОВАТЬ:
Вот сообщение в блоге, которое может быть полезно:
Использование атрибутаCopyToPublishDirectory
может работать в некоторых случаях использования с элементом проекта «Содержимое» или «Нет».CopyToOutputDirectory
также существует.
<ItemGroup>
<Content Include="script\**;external\**" Exclude="external\otherstuff\**;external\results_*\**;external\logs\**" CopyToPublishDirectory="Always" />
</ItemGroup>
Ссылки:
CopyToPublishDirectory
Элемент проекта содержимого
MSBuild включает спецификацию пути.
Лучший способ рекурсивного копирования файлов из одного каталога в другой с использованием MSBuild - это использовать задачу "Копировать" с параметрами SourceFiles и DestinationFiles в качестве параметров. Например, чтобы скопировать все файлы из каталога сборки в каталог резервного копирования,
<PropertyGroup>
<BuildDirectory Condition="'$(BuildDirectory)' == ''">Build</BuildDirectory>
<BackupDirectory Condition="'$(BackupDiretory)' == ''">Backup</BackupDirectory>
</PropertyGroup>
<ItemGroup>
<AllFiles Include="$(MSBuildProjectDirectory)/$(BuildDirectory)/**/*.*" />
</ItemGroup>
<Target Name="Backup">
<Exec Command="if not exist $(BackupDirectory) md $(BackupDirectory)" />
<Copy SourceFiles="@(AllFiles)" DestinationFiles="@(AllFiles->
'$(MSBuildProjectDirectory)/$(BackupDirectory)/%(RecuriveDir)/%(Filename)%
(Extension)')" />
</Target>
Теперь в вышеупомянутой команде Копировать все исходные каталоги просматриваются и файлы копируются в целевой каталог.
Лично я использовал CopyFolder, который является частью библиотеки задач SDC.
Если вы работаете с типичной цепочкой инструментов C++, другой способ - добавить файлы в стандартный список CopyFileToFolders.
<ItemGroup>
<CopyFileToFolders Include="materials\**\*">
<DestinationFolders>$(MainOutputDirectory)\Resources\materials\%(RecursiveDir)</DestinationFolders>
</CopyFileToFolders>
</ItemGroup>
Помимо простоты, это хороший способ, потому что задача CopyFilesToFolders будет генерировать соответствующие входные, выходные и даже файлы TLog, поэтому убедитесь, что операции копирования будут выполняться только тогда, когда один из входных файлов изменился или один из выходных файлов отсутствует. С TLog Visual Studio также правильно распознает проект как "обновленный" или нет (для этого используется отдельный механизм U2DCheck).