Visual Studio: Bagaimana cara "Menyalin ke Direktori Output" tanpa menyalin struktur folder?

111

Saya memiliki beberapa file dll di folder \ lib folder proyek saya. Di halaman properti dll, saya telah memilih "Build Action" sebagai "Content" dan "Copy to Output Directory" sebagai "Copy always".

Setelah membangun saya benar-benar mendapatkan dll disalin tetapi mereka berada di dalam \ bin \ Release \ lib dan bukan di \ bin \ Release.

Apakah ada cara untuk menyalin file dll ke \ bin \ Release (dan bukan ke \ bin \ Release \ lib) tanpa menulis skrip post-build atau menggunakan nant dll?

Oh sayang
sumber

Jawaban:

256

alih-alih <Content>menggunakan <ContentWithTargetPath>dan menentukan jalur target, seperti ini:

<ItemGroup>
  <ContentWithTargetPath Include="lib\some_file.dat">
    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    <TargetPath>some_file.dat</TargetPath>
  </ContentWithTargetPath>
</ItemGroup>

Perhatikan bahwa entri ini mungkin tidak terlihat dari Visual Studio (2012, 2015, 2017), tetapi setelah ditambahkan secara manual ke csproj, entri ini akan muncul di Visual Studio. Namun, jalur target tidak dapat diedit melalui UI.

Daniel Zeitlin
sumber
2
Saya tidak melihat ContentWithTargetPath sebagai opsi Build Action di VS 2015. Apakah ada cara untuk menambahkannya?
Kim
1
Setelah saya menambahkan entri secara manual di file .csproj, entri tersebut muncul sebagai opsi di IDE. Namun saya masih tidak bisa mengedit Path Target dari IDE.
Kim
9
Satu-satunya kekhawatiran saya adalah bahwa ini akan menjadi tidak didukung dengan versi MSBuild / .NET / Visual Studio / Apapun, karena VS2015 UI tidak menampilkan opsi ini atau properti TargetPath.
MarioDS
1
Ini berhasil untuk saya. Tidak ada jawaban lain yang cocok untuk saya. Ini harus menjadi jawabannya.
GunWanderer
1
Perhatikan bahwa menggunakan ContentWithTargetPathkompilasi inkremental jeda (diuji pada VS 2017 15.9.9)
Mads Ravn
26

Simpan $(ProjectDir)\Libfile tersebut, tetapi tambahkan file tersebut " Sebagai link " ke root .csproj Anda. Sekarang mereka akan disalin ke bin \ Debug (atau folder keluaran lainnya) tanpa berada di lib.

EDIT: Jawaban ini ditulis kembali ketika ContentWithTargetPath tidak tersedia di versi VS / MSBuild yang saya gunakan. Meninggalkan jawaban ini di sini untuk orang-orang yang mungkin harus menggunakan versi VS. Tolong berhenti mengomentari ini, kita semua tahu ada cara yang lebih baik sekarang.

Ani
sumber
4
Terima kasih ananthonline. Saya mencoba langkah Anda tetapi tidak membantu. Mungkin saya melakukan sesuatu yang salah. Inilah yang saya lakukan, perbaiki jika menurut Anda ada sesuatu yang salah: 1. Kecualikan dll itu dari proyek tetapi biarkan di lib 2. Klik kanan pada proyek dan "Tambahkan item yang ada". Pilih dll dari lib dan tambahkan "sebagai tautan" 3. Klik kanan pada dll dan sekali lagi pilih "Salin Selalu" dalam "Salin ke Direktori Output". 4. Bersihkan & Bangun Kembali. Hasil: Saya mendapatkan dll itu lagi di \ bin \ release \ lib
OhDear
1
Silakan posting tangkapan layar folder solusi Anda setelah mengonfigurasinya
Ani
3
Jika saya mencoba menambahkan tautan ke file yang sudah ada di pohon proyek, ia menolak dan malah hanya menyertakan file ke dalam proyek lagi ...
Nyerguds
1
Seperti @Nyerguds, saya mengalami bahwa Anda tidak dapat menambahkan tautan ke file yang sudah ada di pohon proyek sehingga jawaban ini tidak menyelesaikan pertanyaan.
Tore Østergaard
1
Bukankah itu membanjiri root direktori proyek di Solution Explorer? Dengan banyaknya file seperti itu, ini bisa menjadi masalah. Biasanya root direktori proyek sudah berisi terlalu banyak file.
Alex34758
10

Jika tujuan utama Anda adalah menyertakan DLL tanpa mengacaukan direktori akar proyek, solusi lainnya adalah memindahkan DLL ke Proyek Bersama yang terpisah dan menambahkannya sebagai referensi dalam proyek asli.

(Perhatikan bahwa posting ini tidak secara langsung menjawab pertanyaan ini karena tidak mempertahankan folder dan struktur proyek, tetapi saya menemukan pendekatan ini berguna karena saya dapat merestrukturisasi proyek saya dalam kasus saya dan karena saya ingin menghindari beberapa kelemahan dari pendekatan lain di sini.)

Langkah

  • Klik kanan file Solution -> Add -> New Project -> Shared Project
  • Tambahkan DLL ke project ini (di direktori root project ini, bukan di sub-folder "lib")
  • (Periksa apakah properti file DLL disetel dengan benar, mis Build Action: Content dan Copy to Output Directory: Copy Always)
  • Klik kanan proyek asli References -> Add Reference -> Shared Projects
  • Pilih proyek bersama yang Anda buat sebelumnya

Penyiapannya terlihat seperti ini:

solution-explorer-screenshot

nak
sumber
2
Sejauh ini, solusi sederhana dan elegan untuk menjaga agar proyek tidak berantakan.
Ravi Ganesh
Saya tidak bisa membuatnya bekerja dengan file UAP dan * .bin.
Matteo
7

Tambahkan dll-files sebagai referensi untuk proyek, dan pada referensi set "Salin lokal" ke true.

erik_nw
sumber
1
Terima kasih Erik. Itu bekerja dengan sempurna kecuali untuk satu dll yang tidak dapat saya tambahkan sebagai referensi. Kesalahan yang saya dapatkan saat menambahkan sebagai referensi adalah Referensi ke 'libeay32.dll' tidak dapat ditambahkan. Harap pastikan bahwa file dapat diakses, dan merupakan komponen assembly atau COM yang valid.
OhDear
7
@MAnthony: Hanya rakitan .NET atau rakitan interop COM yang dapat ditambahkan sebagai referensi proyek; DLL asli tidak boleh. Anda harus menemukan cara lain untuk menyalin DLL ke \ bin \ Release.
Michael Liu
Terima kasih Erik dan Michael dan ananthonline. Maaf tidak dapat memberi suara positif pada jawaban dan komentar Anda karena saya tidak memiliki poin reputasi yang diperlukan.
OhDear
1
Untuk DLL yang tidak dikelola, Anda perlu menggunakan metode yang saya sarankan di bawah ini.
Ani
4

Jika Anda perlu menyalin file dari direktori Libs ke folder root VS2017:

<ItemGroup Condition="'$(Platform)' == 'x64'">
    <None Include="Libs\x64\**" Link="\%(Filename)%(Extension)" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
<ItemGroup Condition="'$(Platform)' == 'x86'">
    <None Include="Libs\x86\**" Link="\%(Filename)%(Extension)" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>

Ke folder lain, termasuk folder Libs (RecursiveDir)

<ItemGroup Condition="'$(Platform)' == 'x86'">
    <None Include="Libs\x86\**" Link="mycustomfolder\%(RecursiveDir)%(Filename)%(Extension)" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
dev-siberia
sumber
3

Tampaknya di VisualStudio 2015 bahwa jika dll yang Anda 'tambahkan dengan tautan' berada dalam subfolder dari proyek yang sama - mereka akan secara otomatis meletakkan folder, dan hasilnya juga ditempatkan di folder seperti yang Anda lihat.

Jika dll berada di proyek atau direktori lain pada disk yang tidak berada dalam subfolder dari proyek tersebut , Anda dapat 'Menambahkan dengan tautan', dan semuanya akan diletakkan di direktori root dengan baik.

DefenestrationDay
sumber
Sama di VS2012. Itu menolak untuk menjadikannya tautan, dan hanya menambahkannya sebagai konten. Pada akhirnya, sayangnya solusi termudah tampaknya untuk membuang mereka di root proyek.
Nyerguds
0

Metode alternatif adalah membiarkan item sebagai tipe None. Di explorer solusi, klik yang ingin Anda terapkan dan setel ContentpropertinyaTrue .

Catatan: Saya melakukan ini di VS2019, dan banyak hal dapat berubah dari versi ke versi.

Untuk membuatnya bekerja, sekarang klik kanan pada proyek Anda, dan pilih "Unload Project". Kemudian klik kanan pada proyek yang dibongkar dan pilih "Edit project_name.vcxproj".

Di editor, pergi ke bagian bawah file dan masukkan target ini tepat sebelum </Project>tag tambahan:

  <Target Name="CopyContent" AfterTargets="Build">
    <Copy SourceFiles="@(None)" Condition="'%(None.DeploymentContent)' == 'true'" DestinationFolder="$(OutputPath)" ContinueOnError="true" />
  </Target>

Sekarang klik kanan pada proyek yang dibongkar dan pilih "Reload Project". Pilih untuk menyimpan dan menutup jika Anda diminta.

Saya juga menyetel OutputDirectoryke:

$(SolutionDir)bin\$(Configuration)\$(Platform)\

dan IntermediateDirectoryke:

$(SolutionDir)obj\$(Configuration)\$(ProjectName)\$(Platform)\

di halaman Project Properties General. Ini menempatkan output dalam folder "bin", dan perantara dalam folder "obj" di root solusi Anda.

Catatan: Tidak $(SolutionDir)ditentukan saat Anda menjalankan MSBuild dari baris perintah. Ada trik yang dapat Anda gunakan untuk menentukannya ke folder tempat file .sln berada menggunakan GetDirectoryNameOfFileAbove. (kiri sebagai latihan untuk pembaca). Juga, sepertinya pada tahun 2019 mereka menangani ini dengan benar di baris perintah. Ya :) The $(SolutionDir)berisi garis miring terbalik, maka tidak ada setelah itu. Hasil dari masing-masing harus memiliki garis miring terbalik.

Sekarang, jika Anda memiliki Pro atau lebih tinggi, jangan lakukan ini setiap kali Anda perlu membuat proyek. Itu akan payah. Sebaliknya, setelah Anda menyiapkan proyek sesuai keinginan Anda, pilih Project -> Export Template. Anda memberinya nama, dan lain kali Anda ingin membuat proyek seperti itu, cukup pilih nama itu di dialog Proyek Baru. (Dalam versi yang lebih lama, saya pikir ini Files -> Export Teamplate....)

ChuckEng
sumber
-1

Saya memiliki masalah yang sama dengan Visual Studio 2010 / C # Project.

Untuk rakitan (yaitu memiliki antarmuka .NET) gunakan folder "Referensi" di bawah proyek Anda di Solution Explorer. Klik kanan, pilih "Tambahkan item yang ada" dan temukan rakitan .dll Anda.

File .dll umum dapat ditempatkan dalam subfolder (seperti "\ lib" disebutkan di atas) dan di properti pilih:

  • Build Action = "HelpFiles"
  • Copy To OutputDirectory = "Jika Lebih Baru"

Ini bekerja untuk saya persis seperti yang diinginkan - selama pembuatan, .DLL disalin ke direktori keluaran tanpa subfolder "\ lib".

Petr Hendl
sumber