Sao chép tất cả các tệp và thư mục bằng msbuild


93

Chỉ tự hỏi nếu ai đó có thể giúp tôi với một số tập lệnh msbuild mà tôi đang cố gắng viết. Những gì tôi muốn làm là sao chép tất cả các tệp và thư mục con từ một thư mục sang thư mục khác bằng msbuild.

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

Những gì tôi cần có thể làm là sao chép tất cả các tệp và thư mục con từ thư mục công cụ vào thư mục gỡ lỗi cho ứng dụng. Đây là mã mà tôi có cho đến nay.

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

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

Tập lệnh xây dựng chạy nhưng không sao chép bất kỳ tệp hoặc thư mục nào.

Cảm ơn

Câu trả lời:


132

Tôi cũng đang tìm kiếm trợ giúp về điều này. Tôi đã mất một lúc, nhưng đây là những gì tôi đã làm rất hiệu quả.

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

Đây đệ quy sao chép nội dung của thư mục có tên antlrcsđến $(TargetDir).


4
Vâng, đây là câu trả lời tốt nhất. Tương tự như được đề xuất ở đây trên blog msdn
Karsten

2
Hoạt động tốt - cảm ơn bạn! Tôi tự hỏi tại sao các câu trả lời khác phức tạp hơn lại có nhiều lượt ủng hộ hơn ?!
Ivan

17
Thủ thuật dường như là thêm %(RecursiveDir)vào thư mục đích sẽ tạo lại cấu trúc thư mục. Nếu không, đầu ra là bằng phẳng. Đây là câu trả lời hay nhất.
JB. Với Monica.

1
Cần phải đặt ở cuối tệp .fsproj, nếu không sẽ không mất.
Henrik

Thời điểm quan trọng ở đây phù hợp với tôi là di chuyển khai báo biến ( <ANTLR Bao gồm = ".. \ Data \ antlrcs ***. *" /> ) Trong mục tiêu AfterBuild. Trong trường hợp của tôi, nó đã được khai báo trong phạm vi bên ngoài và không hoạt động.
Shpand

71

Tôi nghĩ vấn đề có thể nằm ở cách bạn đang tạo Nhóm mục của mình và gọi tác vụ Sao chép. Xem điều này có hợp lý không:

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

CreateItemtác vụ không được dùng nữa. regex có giải pháp thay thế. msdn.microsoft.com/en-us/library/s2y3e43x.aspx
Ray Cheng

35

Tôi là người mới đối với MSBuild nhưng tôi thấy Nhiệm vụ EXEC hữu ích cho những tình huống như thế này. Tôi đã gặp phải thử thách tương tự trong dự án của mình và điều này phù hợp với tôi và đơn giản hơn nhiều. Ai đó vui lòng cho tôi biết nếu nó không phải là một thực hành tốt.

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

9
Tôi dám đặt câu hỏi theo cách khác. Có lý do gì để sử dụng tác vụ sao chép msbuild điền nhật ký không?
bernd_k

4
Có tiềm năng. Nếu bạn có một trang trại xây dựng (Jenkins, TeamCity, v.v.), dịch vụ đại lý có thể chạy trong một tài khoản khác không có xcopy trong đường dẫn. Bạn có thể thử những thứ như% windir% \ system32 trong đường dẫn, nhưng thậm chí điều này không hoạt động một số lần.
Andrew dh

Đó là giải pháp phù hợp với tôi. Ngoài ra, tôi không cần thiết lập WorkingDirectory.
Aebsubis

FYI, tôi cần thêm / Y để chặn lời nhắc ghi đè tệp / thư mục. Ngoài ra, nếu $ (DeploymentDirectory) là một thư mục, để lại dấu "\" sau đường dẫn sẽ xóa lời nhắc: "đích là thư mục hay tệp?"
Hoàng Long

6
Tôi biết vấn đề này không xuất hiện thường xuyên, nhưng lý do chính của tôi để sử dụng Copytác vụ thay vì lệnh là khả năng tương thích. Tôi đã xây dựng trên Linux bằng Mono trước đây và rõ ràng là xcopykhông hoạt động ở đó.
GregRos

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

\**\*.*giúp lấy các tệp từ tất cả các thư mục. RecursiveDir giúp đưa tất cả tệp vào thư mục tương ứng ...


2
Tệp đích đề cập đến 1 mục và tệp nguồn đề cập đến 33 mục. Chúng phải có cùng một số mặt hàng. Ugh .. msbuild có thể tuyệt vời, nhưng đôi khi lại là một mảnh rác được ghi chép kém.
The Muffin Man

CreateItemtác vụ không được dùng nữa. regex có giải pháp thay thế. msdn.microsoft.com/en-us/library/s2y3e43x.aspx
Ray Cheng

4

Bạn đã cố gắng chỉ định thư mục đích cụ thể thay vì

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

Tôi không thành thạo với cú pháp MSBuild nâng cao, nhưng

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

trông kỳ lạ với tôi. Tập lệnh có vẻ ổn, vì vậy vấn đề có thể nằm ở các giá trị $(ApplicationDirectory)$(OutputPath)

BIÊN TẬP:

Đây là một bài đăng trên blog có thể hữu ích:

Cách thực hiện: Sao chép đệ quy tệp bằng tác vụ


1
+1 cho liên kết, ngắn gọn hơn là câu trả lời được chấp nhận từ zXen.
bernd_k

3

Đây là ví dụ đã hoạt động:

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

nguồn: https://msdn.microsoft.com/en-us/library/3e54c37h.aspx


2

Đây là tác vụ sao chép mà tôi đã sử dụng trong dự án của riêng mình, nó hoạt động hoàn hảo đối với tôi khi sao chép thư mục với các thư mục con đến đích thành công:

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

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

Trong trường hợp của tôi, tôi đã sao chép thư mục xuất bản của dự án sang một thư mục đích khác, tôi nghĩ rằng nó tương tự với trường hợp của bạn.



0

Cách tốt nhất để sao chép đệ quy tệp từ thư mục này sang thư mục khác bằng MSBuild là sử dụng tác vụ Sao chép với SourceFiles và DestinationFiles làm tham số. Ví dụ - Để sao chép tất cả các tệp từ thư mục xây dựng sang thư mục sao lưu sẽ

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

Bây giờ trong lệnh Copy ở trên, tất cả các thư mục nguồn được duyệt và các tệp được sao chép vào thư mục đích.


0

Nếu bạn đang làm việc với chuỗi công cụ C ++ điển hình, một cách khác để thực hiện là thêm tệp của bạn vào danh sách CopyFileToFolders tiêu chuẩn

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

Bên cạnh việc đơn giản, đây là một cách tốt để thực hiện vì tác vụ CopyFilesToFolders sẽ tạo ra các đầu vào, đầu ra thích hợp và thậm chí cả tệp TLog, do đó đảm bảo rằng các hoạt động sao chép sẽ chỉ chạy khi một trong các tệp đầu vào đã thay đổi hoặc một trong các tệp đầu ra bị thiếu. Với TLog, Visual Studio cũng sẽ nhận dạng đúng dự án là "cập nhật" hay không (nó sử dụng cơ chế kiểm tra U2DCheck riêng cho việc đó).

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.