Salin semua file dan folder menggunakan msbuild

94

Hanya ingin tahu apakah seseorang dapat membantu saya dengan beberapa skrip msbuild yang saya coba tulis. Yang ingin saya lakukan adalah menyalin semua file dan sub folder dari folder ke folder lain menggunakan msbuild.

{ProjectName}
      |----->Source
      |----->Tools
              |----->Viewer
                       |-----{about 5 sub dirs}

Yang perlu saya lakukan adalah menyalin semua file dan sub folder dari folder alat ke folder debug untuk aplikasi tersebut. Ini adalah kode yang saya miliki sejauh ini.

 <ItemGroup>
<Viewer Include="..\$(ApplicationDirectory)\Tools\viewer\**\*.*" />
 </ItemGroup>

<Target Name="BeforeBuild">
        <Copy SourceFiles="@(Viewer)" DestinationFolder="@(Viewer->'$(OutputPath)\\Tools')" />
  </Target>

Skrip build berjalan tetapi tidak menyalin file atau folder apa pun.

Terima kasih

Nathan W.
sumber

Jawaban:

136

Saya sedang mencari bantuan untuk ini juga. Butuh beberapa saat bagi saya, tetapi inilah yang saya lakukan yang berhasil dengan sangat baik.

<Target Name="AfterBuild">
    <ItemGroup>
        <ANTLR Include="..\Data\antlrcs\**\*.*" />
    </ItemGroup>
    <Copy SourceFiles="@(ANTLR)" DestinationFolder="$(TargetDir)\%(RecursiveDir)" SkipUnchangedFiles="true" />
</Target>

Ini secara rekursif menyalin konten folder yang diberi nama antlrcske $(TargetDir).

Rodolfo Neuber
sumber
4
Ya, inilah jawaban terbaik. Hal yang sama seperti yang direkomendasikan di sini di blog msdn
Karsten
18
Triknya adalah menambahkan %(RecursiveDir)ke folder tujuan akan membuat ulang struktur direktori. Jika tidak, hasilnya akan datar. Ini adalah Jawaban Terbaik.
JB. Dengan Monica.
1
Perlu diletakkan di bagian bawah file .fsproj, atau tidak perlu.
Henrik
Momen kunci di sini yang berhasil bagi saya adalah memindahkan deklarasi variabel ( <ANTLR Include = ".. \ Data \ antlrcs ***. *" /> ) Di bawah target AfterBuild. Dalam kasus saya, itu dideklarasikan di ruang lingkup luar dan tidak berfungsi.
Shpand
Ini ide yang bagus! Saya telah menemukan %(RecursiveDir)di MSBuild metadata item terkenal : docs.microsoft.com/en-us/visualstudio/msbuild/…
kenjiuno
72

Saya pikir masalahnya mungkin pada bagaimana Anda membuat ItemGroup Anda dan memanggil tugas Salin. Lihat apakah ini masuk akal:

<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>
brock.holum
sumber
CreateItemtugas tidak lagi digunakan. regex memiliki alternatif. msdn.microsoft.com/en-us/library/s2y3e43x.aspx
Ray Cheng
35

Saya agak baru mengenal MSBuild tetapi saya menemukan Tugas EXEC berguna untuk situasi seperti ini. Saya menemukan tantangan yang sama dalam proyek saya dan ini berhasil untuk saya dan jauh lebih sederhana. Seseorang tolong beri tahu saya jika ini bukan praktik yang baik.

<Target Name="CopyToDeployFolder" DependsOnTargets="CompileWebSite">
    <Exec Command="xcopy.exe  $(OutputDirectory) $(DeploymentDirectory) /e" WorkingDirectory="C:\Windows\" />
</Target>
Denzil Brown
sumber
9
Saya berani bertanya sebaliknya. Apakah ada alasan untuk menggunakan tugas salin msbuild pengisian log?
bernd_k
4
Berpotensi. Jika Anda memiliki build farm (Jenkins, TeamCity, dll.), Layanan agen dapat berjalan di bawah akun lain yang tidak memiliki xcopy di jalurnya. Anda dapat mencoba hal-hal seperti% windir% \ system32 di jalur, tetapi bahkan ini tidak berhasil beberapa kali.
Andrew dh
Itulah solusi yang berhasil untuk saya. Juga saya tidak perlu mengatur WorkingDirectory.
Aebsubis
FYI, saya perlu menambahkan / Y untuk menekan prompt file / folder override. Juga jika $ (DeploymentDirectory) adalah sebuah folder, meninggalkan "\" setelah jalur akan menghapus prompt: "tujuan adalah folder atau file?"
Hoàng Long
6
Saya tahu masalah ini tidak sering muncul, tetapi alasan utama saya untuk menggunakan Copytugas alih-alih perintah adalah kompatibilitas. Saya telah membangun di Linux menggunakan Mono sebelumnya, dan jelas xcopytidak berfungsi di sana.
GregRos
13
<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>

\**\*.*membantu mendapatkan file dari semua folder. RecursiveDir membantu untuk meletakkan semua file di folder masing-masing ...

amit thakur
sumber
2
File tujuan mengacu pada 1 item dan file sumber mengacu pada 33 item. Mereka harus memiliki jumlah item yang sama. Ugh .. msbuild bisa jadi luar biasa, tapi terkadang sampah seperti itu tidak terdokumentasi dengan baik.
The Muffin Man
CreateItemtugas tidak lagi digunakan. regex memiliki alternatif. msdn.microsoft.com/en-us/library/s2y3e43x.aspx
Ray Cheng
4

Apakah Anda mencoba menentukan direktori tujuan konkret, bukan

DestinationFolder="@(Viewer->'$(OutputPath)\\Tools')" ? 

Saya tidak terlalu mahir dengan sintaks MSBuild tingkat lanjut, tapi

@(Viewer->'$(OutputPath)\\Tools') 

terlihat aneh bagiku. Skrip terlihat bagus, jadi masalahnya mungkin pada nilai $(ApplicationDirectory)dan$(OutputPath)

EDIT:

Berikut adalah posting blog yang mungkin berguna:

Cara: Menyalin File Secara Rekursif Menggunakan Tugas

aku
sumber
1
+1 untuk tautan, yang lebih ringkas dari jawaban yang diterima dari zXen.
bernd_k
3

Ini adalah contoh yang berhasil:

<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>

sumber: https://msdn.microsoft.com/en-us/library/3e54c37h.aspx

PBo
sumber
2

Ini adalah tugas salin yang saya gunakan dalam proyek saya sendiri, ini berfungsi dengan sempurna bagi saya yang berhasil menyalin folder dengan sub folder ke tujuan:

<ItemGroup >
<MyProjectSource Include="$(OutputRoot)/MySource/**/*.*" />
</ItemGroup>

<Target Name="AfterCopy" AfterTargets="WebPublish">
<Copy SourceFiles="@(MyProjectSource)" 
 OverwriteReadOnlyFiles="true" DestinationFolder="$(PublishFolder)api/% (RecursiveDir)"/>

Dalam kasus saya, saya menyalin folder publikasi proyek ke folder tujuan lain, saya pikir itu mirip dengan kasus Anda.

nzrytmn
sumber
1

Secara pribadi saya telah menggunakan CopyFolder yang merupakan bagian dari Perpustakaan Tugas SDC.

http://sdctasks.codeplex.com/

Johan
sumber
0

Cara terbaik untuk menyalin file secara rekursif dari satu direktori ke direktori lain menggunakan MSBuild menggunakan tugas Salin dengan SourceFiles dan DestinationFiles sebagai parameter. Misalnya - Untuk menyalin semua file dari direktori build ke direktori cadangan

<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)/%(RecursiveDir)/%(Filename)% 
(Extension)')" />
</Target>

Sekarang di atas perintah Salin semua direktori sumber dilalui dan file disalin ke direktori tujuan.

shivinder thakur
sumber
0

Jika Anda bekerja dengan toolchain C ++ tipikal, cara lain untuk melakukannya adalah menambahkan file Anda ke dalam daftar CopyFileToFolders standar

<ItemGroup>
  <CopyFileToFolders Include="materials\**\*">
    <DestinationFolders>$(MainOutputDirectory)\Resources\materials\%(RecursiveDir)</DestinationFolders>
  </CopyFileToFolders>
</ItemGroup>

Selain sederhana, ini adalah cara yang bagus untuk melakukannya karena tugas CopyFilesToFolders akan menghasilkan input, output, dan bahkan file TLog yang sesuai oleh karena itu memastikan bahwa operasi penyalinan hanya akan berjalan ketika salah satu file input telah berubah atau salah satu file output hilang. Dengan TLog, Visual Studio juga akan mengenali proyek dengan benar sebagai "up to date" atau tidak (menggunakan mekanisme U2DCheck terpisah untuk itu).

Sergei Ozerov
sumber