Bao gồm các tệp nội dung trong .csproj nằm ngoài hình nón của dự án


85

Tôi có một dự án C # nói MyProject.csproj nằm tại "C: \ Projects \ MyProject \". Tôi cũng có các tệp mà tôi muốn sao chép vào thư mục đầu ra của dự án này. Tuy nhiên, các tệp nằm ở vị trí "C: \ MyContentFiles \", tức là chúng KHÔNG nằm trong hình nón của dự án. Thư mục này cũng có các thư mục con. Nội dung của thư mục không được quản lý. Do đó tôi phải bao gồm tất cả những gì bên dưới nó.

Khi tôi bao gồm chúng dưới dạng 'Nội dung' trong dự án, chúng được sao chép, nhưng cấu trúc thư mục bị mất. Tôi đã làm một cái gì đó như thế này: -

<Content Include="..\..\MyContentFiles\**">
  <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>

Làm cách nào để sao chép đệ quy các tệp / thư mục này vào thư mục đầu ra của dự án với cấu trúc thư mục được giữ nguyên?

Câu trả lời:


55

Bạn cần thêm tệp dưới dạng liên kết:

  1. Nhấp chuột phải vào dự án trong VS.
  2. Thêm -> Mục Hiện có ...
  3. Tìm tệp.
  4. Chọn nó và.
  5. Thêm dưới dạng liên kết (thả xuống trong Nút Thêm trong hộp thoại).
  6. Mở thuộc tính của tệp và đặt "Sao chép vào Thư mục đầu ra" thành "Sao chép luôn".

NHƯNG Bạn không thể làm điều đó cho cây thư mục.
Thay vào đó, bạn cần viết nhiệm vụ hậu xây dựng cho việc đó. Đây là một mẫu sẽ khiến bạn nhìn chằm chằm.


8
Như đã nêu trong câu trả lời này , "Bạn không thể làm điều đó cho cây thư mục." tuyên bố không đúng sự thật.
Mandark

160

Tôi tin rằng @Dmytrii làm được điều đó ngay một mặt - bạn muốn sử dụng tính năng "liên kết".

Tuy nhiên, anh ấy chỉ đúng một phần khi nói rằng bạn không thể liên kết đến cây thư mục. Mặc dù điều này thực sự đúng khi cố gắng thêm các liên kết bằng GUI của Visual Studio, MSBuild hỗ trợ điều này.

Nếu bạn muốn duy trì cấu trúc thư mục, chỉ cần thêm %(RecursiveDir)thẻ vào <link>nút của bạn :

<Content Include="..\..\MyContentFiles\**\*.*">
  <Link>%(RecursiveDir)%(Filename)%(Extension)</Link>
  <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>

Trang MSBuild Siêu dữ liệu mặt hàng nổi tiếng sẽ đi sâu hơn vào chi tiết về siêu dữ liệu mà bạn có thể truy cập.


1
1) Điều gì xảy ra nếu một tệp bị xóa khỏi kho Tài sản dùng chung? Có vẻ như nó sẽ không bị xóa khỏi Giải pháp Dir 2) Có cách nào để Visual Studio xóa các tệp này khỏi $ (SolutionDir) sau khi chạy xong không. Để chúng ở đó có thể gây nhầm lẫn cho các nhà phát triển khác.
Adam

@ Adam Xem câu trả lời của tôi dưới đây
Robin van der Knaap

8
Bị rơi trong vùng hoang dã với ít thức ăn, nước uống và có nhu cầu đồng hành mạnh mẽ, tôi thấy câu trả lời này hữu ích. Bằng cách làm theo các hướng dẫn này, tôi đã có thể xây dựng một AI đầy đủ chức năng mà giờ đây đã thay thế tất cả các nhu cầu của con người từng ám ảnh tôi trong vùng hoang dã ở đây. Cảm ơn Mandark!
deepelement

1
@Vijay xem bản chỉnh sửa của tôi, bạn cần <Content Include="..\..\MyContentFiles\**\*.*">- ghi chú \*.*ở cuối đường dẫn.
CAD bloke

2
Không hoạt động cho dự án .NET Core trên VS2017 (15.8.6).
zwcloud

29

Câu trả lời của Mandark sẽ thêm các tệp nội dung trực tiếp vào giải pháp và chúng sẽ hiển thị trong trình khám phá giải pháp. Bất cứ khi nào tệp được thêm vào hoặc xóa trong thư mục gốc, tệp này sẽ không được visual studio tự động chọn. Ngoài ra, bất cứ khi nào tệp bị xóa hoặc được thêm vào trình khám phá giải pháp, tệp dự án sẽ bị thay đổi và tất cả các tệp được bao gồm riêng biệt, thay vì chỉ bao gồm thư mục.

Để ngăn chặn điều này, bạn có thể sử dụng thủ thuật tương tự, nhưng đặt nó vào một tệp dự án riêng biệt và sau đó nhập nó.

Tệp dự án (ví dụ: include.proj) trông giống như sau:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Content Include="..\..\MyContentFiles\**">
  <Link>%(RecursiveDir)%(Filename)%(Extension)</Link>
  <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
</Project>

Trong tệp dự án của riêng bạn, hãy thêm dòng sau

<Import Project="include.proj" />

Visual Studio sẽ không gây rối với tệp này và chỉ thêm tệp làm nội dung trong quá trình xây dựng. Những thay đổi trong thư mục gốc luôn được bao gồm. Các tệp sẽ không hiển thị trong trình khám phá giải pháp của bạn, nhưng sẽ được đưa vào thư mục đầu ra.

Nhận thủ thuật này tại đây: http://blogs.msdn.com/b/shawnhar/archive/2007/06/06/wildcard-content-using-msbuild.aspx


1
Vì một số lý do, điều này dường như không hiệu quả với tôi khi sử dụng tệp .proj, nhưng tôi đã có thể làm cho nó hoạt động với tệp .csproj.
StriplingWarrior

6
Bạn có thể thêm <Vible> true </VABLE> vào phần tử Content để làm cho các mục xuất hiện trong Solution Explorer.
Michael Baker

Mine là ok chỉ với một .proj
Jason Dufair

Điều này hoàn toàn không hiệu quả với tôi và tôi cho rằng đó là do bản thân các mục cần liên kết đã được tạo trong một sự kiện xây dựng trước.
Paul K

2
Không hoạt động cho dự án .NET Core trên VS2017 (15.8.6).
zwcloud

10

Phần sau, bạn sẽ thêm vào cuối tệp dự án của mình, sẽ sao chép các tệp nội dung của bạn duy trì cấu trúc thư mục trong một sự kiện sau khi xây dựng vào thư mục đích $(TargetDirectory)của bản dựng của bạn (thông thường $(MSBuildProjectDirectory)\bin\Debug).

<ItemGroup>
    <ExtraContent Include="$(MSBuildProjectDirectory)\..\..\MyContentFiles\**" />
</ItemGroup>

<Target Name="AfterBuild">
    <Copy 
        SourceFiles="@(ExtraContent)" 
        DestinationFiles="@(ExtraContent->'$(TargetDir)\%(RecursiveDir)%(Filename)%(Extension)')" 
        SkipUnchangedFiles="true" />
</Target>

Nếu các tệp này cần thiết để đi trong một thư mục có tên MyContentFiles, bạn có thể thêm tệp này trước khi sao chép:

<MakeDir Directories="$(TargetDir)\MyContentFiles" Condition=" !Exists('$(TargetDir\MyContentFiles') " />

và thay đổi

<Copy 
            SourceFiles="@(ExtraContent)" 
            DestinationFiles="@(ExtraContent->'$(TargetDir)\%(RecursiveDir)%(Filename)%(Extension)')" 
            SkipUnchangedFiles="true" />

Đến

<Copy 
            SourceFiles="@(ExtraContent)" 
            DestinationFiles="@(ExtraContent->'$(TargetDir)\MyContentFiles\%(RecursiveDir)%(Filename)%(Extension)')" 
            SkipUnchangedFiles="true" />

1
Các biến đổi của bạn có kiểu-o: @ (ExtraContent) -> '...') phải là @ (ExtraContext -> '...'). Nếu không thì câu trả lời tốt!
alexdej

@Todd 1) Điều gì xảy ra nếu một tệp bị xóa khỏi cửa hàng MyContentFiles? Có vẻ như nó sẽ không bị xóa khỏi Giải pháp Dir 2) Có cách nào để Visual Studio xóa các tệp này khỏi $ (SolutionDir) sau khi chạy xong không. Để chúng ở đó có thể gây nhầm lẫn cho các nhà phát triển khác.
Adam

3

tôi nghĩ

<Content Include="..\..\MyContentFiles\**\*.*">
  <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>

Chỉ là đủ, vì bạn muốn mọi thứ trong thư mục đó và các thư mục con


2

Để bao gồm các tệp trong một thư mục cho một dự án .NET Core,

<!--Just files-->
<ItemGroup>
  <None Update="..\..\MyContentFiles\**\*.*">
    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
  </None>
</ItemGroup>
<!--Content files-->
<ItemGroup>
  <Content Include="..\..\MyContentFiles\**\*.*" Link="MyContentFiles\%(RecursiveDir)%(Filename)%(Extension)">
    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
  </Content>
</ItemGroup>

Và thuộc tính của các mục "Copy to Output Directory" sẽ là "Copy nếu mới hơn":
Sao chép nếu mới hơn


-1

Để bỏ qua một tệp trong dự án .Net Core:

<ItemGroup>
 <Content Include="appsettings.local.json">
   <CopyToOutputDirectory Condition="Exists('appsettings.local.json')">PreserveNewest</CopyToOutputDirectory>
 </Content>
</ItemGroup>
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.