Msbuild kullanarak tüm dosya ve klasörleri kopyalayın


94

Birinin yazmaya çalıştığım bazı msbuild komut dosyalarında bana yardım edip edemeyeceğini merak ediyorum. Yapmak istediğim şey, msbuild kullanarak tüm dosyaları ve alt klasörleri bir klasörden başka bir klasöre kopyalamak.

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

Yapabilmem gereken şey, tüm dosyaları ve alt klasörleri araçlar klasöründen uygulamanın hata ayıklama klasörüne kopyalamak. Şimdiye kadar sahip olduğum kod bu.

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

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

Derleme betiği çalışır, ancak dosya veya klasörlerin hiçbirini kopyalamaz.

Teşekkürler

Yanıtlar:


136

Ben de bu konuda yardım arıyordum. Biraz zaman aldı ama işte yaptığım şey gerçekten işe yaradı.

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

Bu yinelemeli adlı klasörün içeriğini kopyaladığınız antlrcsiçin $(TargetDir).


4
Evet, bu en iyi cevap. Msdn
Karsten

18
İşin püf %(RecursiveDir)noktası, hedef klasöre eklemenin dizin yapısını yeniden oluşturması gibi görünüyor . Aksi takdirde çıktı düzdür. Bu, En İyi Cevap.
JB. Monica ile.

1
.Fsproj dosyasının en altına yerleştirilmesi gerekiyor , yoksa sürmez.
Henrik

Benim için işe yarayan en önemli an, değişken bildirimini ( <ANTLR Include = ".. \ Data \ antlrcs ***. *" /> ) AfterBuild hedefi altına taşımaktır. Benim durumumda dış kapsamda ilan edildi ve işe yaramadı.
Shpand

Bu harika bir fikir! Ben bulduk %(RecursiveDir)içinde MSBuild tanınmış öğe meta : docs.microsoft.com/en-us/visualstudio/msbuild/...
kenjiuno

72

Sanırım sorun, ItemGroup'unuzu nasıl oluşturduğunuzda ve Kopyala görevini nasıl çağırdığınızda olabilir. Bunun mantıklı olup olmadığına bakın:

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

CreateItemgörev kullanımdan kaldırıldı. regex'in alternatifi vardır. msdn.microsoft.com/en-us/library/s2y3e43x.aspx
Ray Cheng

35

MSBuild'de yeniyim ama bu gibi durumlar için EXEC Görevini kullanışlı buluyorum. Projemde de aynı zorlukla karşılaştım ve bu benim için çalıştı ve çok daha basitti. Birisi lütfen iyi bir uygulama değilse bana bildirin.

<Target Name="CopyToDeployFolder" DependsOnTargets="CompileWebSite">
    <Exec Command="xcopy.exe  $(OutputDirectory) $(DeploymentDirectory) /e" WorkingDirectory="C:\Windows\" />
</Target>

9
Soruyu tam tersi sormaya cüret ediyorum. Msbuild kopyalama görevini dolduran günlüğü kullanmak için herhangi bir neden var mı?
bernd_k

4
Potansiyel olarak. Bir yapı grubunuz varsa (Jenkins, TeamCity vb.), Aracı hizmeti yolda xcopy olmayan farklı bir hesap altında çalışabilir. Yolda% windir% \ system32 gibi şeyleri deneyebilirsiniz, ancak bu bile bazen çalışmaz.
Andrew dh

Benim için işe yarayan çözüm buydu. Ayrıca WorkingDirectory'yi ayarlamama gerek yoktu.
Aebsubis

Bilginize, dosya / klasör geçersiz kılma istemini bastırmak için / Y eklemem gerekiyor. Ayrıca $ (DeploymentDirectory) bir klasörse, yoldan sonra bir "\" bırakmak "hedef klasör mü yoksa dosya mı?" Komut istemini kaldıracaktır.
Hoàng Uzun

6
Bu sorunun çok sık ortaya çıkmadığını biliyorum, ancak Copygörevi komut yerine kullanmak için ana nedenim uyumluluk. Daha önce Mono kullanarak Linux üzerine inşa ettim ve açıkçası xcopyorada çalışmıyor.
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>

\**\*.*tüm klasörlerden dosya almak için yardım. RecursiveDir, tüm dosyayı ilgili klasöre koymak için yardım ...


2
Hedef dosyalar 1 öğe ve kaynak dosyalar 33 öğe anlamına gelir. Aynı sayıda öğeye sahip olmaları gerekir. Ugh .. msbuild harika olabilir, ancak bazen çok az belgelenmiş bir hurda parçası.
Kek Adam

CreateItemgörev kullanımdan kaldırıldı. regex'in alternatifi vardır. msdn.microsoft.com/en-us/library/s2y3e43x.aspx
Ray Cheng

4

Yerine somut bir hedef dizin belirtmeye çalıştınız mı?

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

Gelişmiş MSBuild sözdizimi konusunda çok deneyimli değilim, ancak

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

bana tuhaf görünüyor. Sorun değerlerinde olabilir böylece Senaryo, iyi görünüyor $(ApplicationDirectory)ve$(OutputPath)

DÜZENLE:

İşte yararlı olabilecek bir blog yazısı:

Nasıl Yapılır: Görevi Kullanarak Dosyaları Yinelemeli Olarak Kopyalama


1
Bağlantı için +1, zXen'den kabul edilen cevaptan daha özlü.
bernd_k

3

Bu işe yarayan örnek:

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

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


2

Bu, kendi projemde kullandığım kopyalama görevi, benim için mükemmel çalışıyordu, alt klasörleri olan klasörü başarıyla hedefe kopyaladı:

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

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

Benim durumumda, bir projenin yayınlama klasörünü başka bir hedef klasöre kopyaladım, bunun sizin durumunuza benzer olduğunu düşünüyorum.



0

MSBuild kullanarak dosyaları bir dizinden diğerine yinelemeli olarak kopyalamanın en iyi yolu, parametre olarak SourceFiles ve DestinationFiles ile Kopyalama görevini kullanmaktır. Örneğin - Tüm dosyaları derleme dizininden yedekleme dizinine kopyalamak

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

Şimdi yukarıdaki Kopyala komutunda tüm kaynak dizinler arasında geçiş yapılır ve dosyalar hedef dizine kopyalanır.


0

Tipik C ++ araç zinciriyle çalışıyorsanız, başka bir yol da dosyalarınızı standart CopyFileToFolders listesine eklemektir.

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

Basit olmasının yanı sıra, bu gitmek için güzel bir yoldur çünkü CopyFilesToFolders görevi uygun girdileri, çıktıları ve hatta TLog dosyalarını üretecektir, bu nedenle kopyalama işlemlerinin yalnızca girdi dosyalarından biri değiştiğinde veya çıktı dosyalarından biri eksik olduğunda çalışacağından emin olun. TLog ile Visual Studio, projeyi "güncel" olarak doğru bir şekilde tanıyacaktır (bunun için ayrı bir U2DCheck mekanizması kullanır).

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.