DLL dependen tidak mendapatkan disalin ke folder output build di Visual Studio

188

Saya punya solusi studio visual. Saya punya banyak proyek dalam solusinya. Ada satu proyek utama yang bertindak sebagai permulaan dan menggunakan proyek lain. Ada satu proyek yang mengatakan "ProjectX". Rujukannya ditambahkan ke proyek utama. The ProjectX referensi lain .NET dll (katakanlah abc.dll) yang bukan bagian dari solusi.

Sekarang abc.dll ini harus disalin ke folder bin / debug proyek utama, tetapi tidak disalin di sana. Mengapa tidak disalin, ada alasan yang diketahui?

Brij
sumber
jika Anda tidak dapat mengetahuinya, salin di prebuild Anda.
Dilshod
bagaimana Anda menggunakan 'ProjectX' Anda di proyek utama - apa jenis proyek, target dll.
NSGaga-kebanyakan-tidak aktif
Saya memiliki masalah yang sama dan jawaban ini memecahkan masalah saya: stackoverflow.com/a/8213977/174469
Gordon Tucker
ada RestoreProjectStyle solusi yang tersedia . Idenya adalah mengatur <RestoreProjectStyle>PackageReference</RestoreProjectStyle>untuk setiap proyek .Net Framework dalam solusinya.
oleksa

Jawaban:

105

Saya menemukan bahwa jika ProjectX mereferensikan abc.dll tetapi tidak secara langsung menggunakan salah satu tipe yang didefinisikan dalam abc.dll, maka abc.dll TIDAK akan disalin ke folder output utama. (Ini akan disalin ke folder keluaran ProjectX, untuk membuatnya sangat membingungkan.)

Jadi, jika Anda tidak secara eksplisit menggunakan salah satu jenis dari abc.dll di mana saja di ProjectX, maka letakkan deklarasi dummy di suatu tempat di salah satu file di ProjectX.

AbcDll.AnyClass dummy006; // this will be enough to cause the DLL to be copied

Anda tidak perlu melakukan ini untuk setiap kelas - sekali saja cukup untuk membuat salinan DLL dan semuanya berfungsi seperti yang diharapkan.

Tambahan: Perhatikan bahwa ini mungkin bekerja untuk mode debug, tetapi BUKAN untuk rilis. Lihat jawaban @ nvirth untuk detailnya.

Tuan Zurg
sumber
7
Ini seperti retasan. Menambahkan referensi ke proyek utama tampaknya sudah cukup.
Mike K
3
Ini IS hack, tapi seperti yang diajarkan oleh berita CodeProject hari ini, bahkan kompiler pun bisa salah!
Tuan Zurg
4
Betapa gilanya hal itu. @OverlordZurg solusi Anda bekerja karena saya memiliki referensi ke dll tergantung di XAML (WPF) saya dan itu tidak menyalin DLL ke proyek utama sampai saya menambahkan referensi boneka sederhana seperti yang Anda katakan ... Terima kasih
Mohsen Afshin
5
@MohsenAfshin Saya punya masalah yang sama --- Saya mereferensikan DLL dependen di XAML. Alih-alih mendeklarasikan variabel dummy, saya hanya menyebutkan komponen yang saya gunakan di XAML, dan itu cukup untuk menyebabkan rakitannya disalin.
redcurry
5
@MikeK Menambahkannya ke proyek utama (yang sebenarnya tidak bergantung padanya) adalah peretasan yang lebih besar, imo. Maka Anda harus mengelolanya dua tempat ("kelola" seperti dalam meningkatkan atau menghapus). Dengan peretasan ini , setidaknya Anda mendapatkan kesalahan waktu kompilasi yang bagus mengingatkan Anda untuk menghapus peretasan ini saat Anda menghapus ketergantungan, dan Anda masih hanya perlu memperbaruinya di satu tempat.
jpmc26
71

Hanya sidenote jawaban Overlord Zurg.

Saya telah menambahkan referensi dummy dengan cara ini, dan itu berfungsi dalam mode Debug:

public class DummyClass
{
    private static void Dummy()
    {
        var dummy = typeof(AbcDll.AnyClass);
    }
}

Tetapi dalam mode Release, dll tergantung masih tidak bisa disalin.
Namun ini berhasil:

public class DummyClass
{
    private static void Dummy()
    {
        Action<Type> noop = _ => {};
        var dummy = typeof(AbcDll.AnyClass);
        noop(dummy);
    }
}

Informasi ini sebenarnya menghabiskan waktu berjam-jam untuk mencari tahu, jadi saya pikir saya membagikannya.

nvirth
sumber
7
dalam mode rilis, pengoptimal menganggap bahwa "dummy" tidak digunakan sehingga baris ini tidak perlu dan harus dihapus. tetapi ketika Anda menggunakan "dummy" dalam kode, pengoptimal tidak menganggapnya tidak perlu.
Yucel
1
ini tidak berfungsi untuk saya. Accll. AnyClass masih belum disalin ke proyek lain
Matthew Lock
3
Pastikan AbcDll.AnyClassdigunakan sebagai bidang publik atau properti di kelas publik, maka itu akan berhasil. Jika Anda menggunakannya dalam tubuh metode seperti ini kompiler tidak melihatnya . Ini akan menunda memuat rakitan ini, bukan apa yang Anda inginkan terjadi.
John Leidegren
52

Ya, Anda harus mengatur Copy Localke true. Namun, aku cukup yakin Anda juga harus referensi yang perakitan dari proyek utama dan set Copy Localuntuk truejuga - itu tidak hanya disalin dari perakitan tergantung.

Anda dapat pergi ke Copy Localproperti dengan mengklik rakitan di bawah Referencesdan menekan F4.

Mike Perrenoud
sumber
2
@ Brij, apakah perakitan dirujuk dari proyek utama yang Anda inginkan? Seperti yang saya katakan, saya cukup yakin Anda perlu referensi dari proyek itu juga majelis tergantung tidak disalin seperti itu. Jika demikian, Anda tidak perlu menambahkan rakitan ke semua proyek yang relevan saat menggunakan NuGet.
Mike Perrenoud
1
apa kesimpulannya di sini? Tampak bagi saya bahwa Anda benar - tergantung referensi tidak disalin bahkan jika CopyLocal disetel ke true - apa logika di balik itu?
mcmillab
29
@mcmillab, singkatnya Visual Studio tidak menyimpulkan ketergantungan dari proyek dependen lainnya. Jika proyek A referensi proyek B, proyek A perlu memiliki semua referensi proyek B. Ini bekerja dengan baik ketika semua kebutuhan proyek B adalah. NET rakitan, tetapi jika itu adalah rakitan pihak ke-3 Anda harus menambahkan referensi ke kedua proyek.
Mike Perrenoud
12
@MichaelPerrenoud Saya tidak berpikir itu benar. Jika Anda melihat output MSBuild yang terperinci, Anda akan melihat panggilan ke ResolveAssemblyReference yang menyatakannya "termasuk dependensi urutan kedua dan urutan ke-n". Ini juga sesuai dengan apa yang saya lihat di folder bin saya (dependensi ke-n disalin). Masalahnya adalah ada beberapa peringatan tentang apa yang disalin, sebagian besar di sekitar GAC dan referensi tidak langsung (Tambahkan Referensi kadang-kadang tidak cukup)
Jack Ukleja
2
Pengalaman saya saat ini adalah bahwa ini akan berfungsi kecuali untuk dependensi 'disalin': project A.net mereferensikan eksternal C ++ dll sebagai file yang 'copy selalu'. Referensi Proyek B.net Proyek A. Sedang dibangun, B / Debug menyertakan C ++ dll. Namun, ketika saya membangun Aplikasi X, yang merujuk Proyek B, C ++ dll kadang-kadang disalin (tampaknya hanya jika saya melakukan Rebuild).
Benjol
34

Ini terlihat apik ketika Anda membuatnya menjadi atribut perakitan

[AttributeUsage(AttributeTargets.Assembly)]
public class ForceAssemblyReference: Attribute
{        
    public ForceAssemblyReference(Type forcedType)
    {
        //not sure if these two lines are required since 
        //the type is passed to constructor as parameter, 
        //thus effectively being used
        Action<Type> noop = _ => { };
        noop(forcedType);
    }
}

Penggunaannya akan:

[assembly: ForceAssemblyReference(typeof(AbcDll.AnyClass))]
Aryéh Radlé
sumber
Terima kasih, tetapi bagi saya ini hanya melakukan sesuatu ketika saya menambahkan atribut perakitan ke dependensi (Proyek X), yang sudah mereferensikan AbcDll.AnyClass. Dan kemudian, itu tidak melakukan lebih dari biasanya, di mana ia menyalin AbcDll ke direktori output dependensi. Itu masih tidak menyalinnya ke output proyek tergantung utama. Dan saya tidak bisa menambahkan atribut ke perakitan tergantung kecuali saya juga menambahkan referensi ke AbcDll. Ketika saya melakukan itu, AbcDll sudah akan disalin tanpa atribut.
JS
25

Berlari ke masalah yang sama ini. Info latar belakang: sebelum membangun, saya telah menambahkan Project X baru ke solusinya. Proyek Y tergantung pada Proyek X dan Proyek A, B, C tergantung pada Proyek Y.

Kesalahan build adalah bahwa proyek, A, B, C, Y, dan X dll tidak dapat ditemukan.

Penyebab root adalah bahwa Proyek X yang baru dibuat menargetkan .NET 4.5 sedangkan sisanya dari proyek solusi menargetkan .NET 4.5.1. Proyek X tidak membangun menyebabkan sisa Proyek tidak membangun juga.

Pastikan setiap Proyek yang baru ditambahkan menargetkan versi .NET yang sama dengan solusi lainnya.

Darren Alfonso
sumber
1
Proyek yang dirujuk mungkin merupakan versi .NET yang lebih lama. Saya dapat merujuk proyek yang dibangun untuk .NET 4 oleh proyek yang dibangun untuk .NET 4.5.
redcurry
18

Tidak yakin apakah ini membantu tetapi bagi saya, berkali-kali saya merujuk DLL (yang secara otomatis menambahkannya ke folder bin tentu saja). Namun DLL itu mungkin memerlukan DLL tambahan (tergantung pada fungsi apa yang saya gunakan). Saya TIDAK ingin referensi yang ada di Proyek saya karena mereka hanya perlu berakhir di folder yang sama dengan DLL yang sebenarnya saya gunakan.

Saya melakukannya di Visual Studio dengan "Menambahkan file yang ada". Anda harus dapat menambahkannya di mana saja kecuali folder Add_data. secara pribadi saya hanya menambahkannya ke root.

Kemudian ubah properti file itu menjadi ...

Build Action = Tidak Ada (memiliki set ini untuk sesuatu seperti Konten benar-benar menyalin versi "root" ke root, ditambah salinan di Bin).

Salin ke folder keluaran = Salin jika Lebih Baru (Pada dasarnya menempatkannya di folder BIN hanya jika hilang, tetapi tidak melakukannya setelah itu)

Ketika saya mempublikasikan .. DLL tambahan saya hanya ada di folder BIN dan tidak ada tempat lain di lokasi Publikasikan (yang saya inginkan).

da_jokker
sumber
10

Anda juga dapat memeriksa untuk memastikan DLL yang Anda cari tidak termasuk dalam GAC. Saya percaya Visual Studio pintar tidak menyalin file-file itu jika sudah ada di GAC pada mesin build.

Saya baru-baru ini berlari dalam situasi ini di mana saya telah menguji paket SSIS yang membutuhkan rakitan untuk ada di GAC. Sejak itu saya lupa itu dan bertanya-tanya mengapa DLL itu tidak keluar saat membangun.

Untuk memeriksa apa yang ada di GAC (dari Prompt Perintah Pengembang Visual Studio):

gacutil -l

Atau keluaran ke file untuk membuatnya lebih mudah dibaca:

gacutil -l > output.txt
notepad.exe output.txt

Untuk menghapus unit:

gacutil -u MyProjectAssemblyName

Saya juga harus mencatat, bahwa setelah saya menghapus file-file dari GAC, mereka benar output di direktori \ bin setelah membangun (Bahkan untuk rakitan yang tidak secara langsung direferensikan dalam proyek root). Ini pada Visual Studio 2013 Pembaruan 5.

Brett
sumber
Terima kasih, Anda benar, MSBuild tidak akan menyalin dll ke folder keluaran jika ditemukan di GAC.
John-Philip
3

Dalam kasus saya, itu adalah hal yang paling bodoh, yang disebabkan oleh perilaku default TFS / VS yang tidak saya setujui.

Karena menambahkan dll sebagai referensi ke proyek utama tidak berhasil, saya memutuskan untuk menambahkannya sebagai "Item yang Ada", dengan Salin Lokal = Selalu. Bahkan kemudian file itu tidak ada di sana.

Ternyata itu, meskipun file hadir pada Solusi VS dan semuanya dikompilasi secara lokal dan di server, VS / TFS tidak menambahkan sebenarnya menambahkan file ke kontrol sumber. Sama sekali tidak termasuk dalam "Perubahan yang Ditangguhkan". Saya harus secara manual pergi ke Explorer Kontrol Sumber dan secara eksplisit klik ikon "Tambahkan item ke folder".

Bodoh karena saya sudah berkembang selama 15 tahun di VS. Saya pernah mengalami ini sebelumnya, saya hanya tidak ingat dan entah bagaimana saya melewatkannya karena semuanya masih dikompilasi karena file menjadi referensi biasa, tetapi file yang ditambahkan sebagai Item yang Ada tidak disalin karena tidak ada pada server kontrol sumber.

Saya harap ini menghemat waktu seseorang, karena saya kehilangan 2 hari hidup saya untuk ini.

GR7
sumber
1
Saya tidak bisa cukup berterima kasih ... Anda telah menyelamatkan saya banyak waktu. Ini solusi bagi saya. Itu juga terkena masalah root, DLL yang saya tambahkan sebagai referensi cocok dengan gitignorepola, jadi ketika menambahkan sebagai referensi itu tidak menambah proyek. Anda HARUS menambahkan file secara manual ke kontrol sumber !!!
Mattkwish
2

Ini adalah sedikit perubahan pada contoh nvirth

internal class DummyClass
{
    private static void Dummy()
    {
        Noop(typeof(AbcDll.AnyClass));
    }
    private static void Noop(Type _) { }
}
maca134
sumber
2

Saya akan menambahkannya ke acara Postbuild untuk menyalin pustaka yang diperlukan ke direktori keluaran. Sesuatu seperti XCopy pathtolibrary targetdirectory

Anda dapat menemukannya di properti proyek -> Bangun Acara.

chethan jain
sumber
Ini bekerja untuk saya, dan saya pikir ini adalah jawaban yang lebih baik. Solusi referensi dummy berfungsi, tapi ini peretasan, sedangkan aturan post-build adalah cara yang bersih untuk mencapai hasil yang sama.
Kevin Fichter
2

Isu:

Menemukan masalah serupa untuk DLL paket NuGet (Newtonsoft.json.dll) di mana output build tidak termasuk DLL yang direferensikan. Tapi kompilasi berjalan lancar.

Memperbaiki:

Telusuri proyek Anda dalam editor teks dan cari referensi dengan tag di dalamnya. Suka Benar atau Salah. "Pribadi" adalah sinonim untuk "Salin Lokal." Di suatu tempat dalam tindakan, MSBuild mengambil untuk menemukan dependensi, ia menemukan ketergantungan Anda di tempat lain dan memutuskan untuk tidak menyalinnya.

Jadi, buka setiap file .csproj / .vbproj dan hapus tag secara manual. Rebuild, dan semuanya berfungsi di Visual Studio dan MSBuild. Setelah berhasil, Anda dapat kembali dan memperbarui ke tempat yang Anda pikir perlu.

Referensi:

https://www.paraesthesia.com/archive/2008/02/13/what-to-do-if-copy-local-works-in-vs-but.aspx/

Nkl Kumar
sumber
1

TIDAK PERLU DUMMY DALAM KODE
Hanya:

tambahkan Referensi ke Proyek Executeable

atau / dan memastikan bahwa referensi dalam proyek yang dapat dieksekusi telah "Copy Local"disetel ke TRUE(yang merupakan " kesalahan " saya) tampaknya bahwa "menimpa" pengaturan di pangkalan-proyek referensi perpustakaan ...

Cadburry
sumber
1

Jika Anda mengklik kanan rakitan yang direferensikan, Anda akan melihat properti yang disebut Salin Lokal . Jika Salin Lokal disetel ke true, maka perakitan harus disertakan dalam nampan. Namun , ada masalah dengan Visual studio, yang kadang-kadang tidak termasuk dll yang direferensikan dalam folder bin ... ini adalah solusi yang bekerja untuk saya:

masukkan deskripsi gambar di sini

Hooman Bahreini
sumber
1
Copy Loal dinonaktifkan, ini membantu stackoverflow.com/questions/15526491/…
codemirror
1

TLDR; Visual Studio 2019 mungkin hanya perlu restart.

Saya mengalami situasi ini menggunakan proyek berdasarkan proyek Microsoft.NET.Sdk.

<Project Sdk="Microsoft.NET.Sdk">

Secara khusus:

  • Project1: target .netstandard2.1
    • referensi Microsoft.Extensions.Logging.Consolemelalui Nuget
  • Project2: target .netstandard2.1
    • referensi Project1melalui referensi Proyek
  • Project2Tests: target .netcoreapp3.1
    • referensi Project2melalui referensi Proyek

Pada pelaksanaan pengujian, saya menerima pesan kesalahan yang menunjukkan bahwa Microsoft.Extensions.Logging.Consoletidak dapat ditemukan, dan itu memang tidak ada di direktori output.

Aku memutuskan untuk bekerja di sekitar masalah ini dengan menambahkan Microsoft.Extensions.Logging.Consoleuntuk Project2, hanya untuk menemukan bahwa Visual Studio Nuget Manajer tidak daftar Microsoft.Extensions.Logging.Consolesebagai dipasang di Project1, meskipun kehadiran itu dalam Project1.csprojberkas.

Sederhana mematikan dan memulai kembali Visual Studio menyelesaikan masalah tanpa perlu menambahkan referensi tambahan. Mungkin ini akan menghemat seseorang 45 menit dari kehilangan produktivitas :-)

Eric Patrick
sumber
Sebenarnya saya me
Noman_1
0

Anda dapat mengatur proyek utama dan membangun jalur output ProjectX ke folder yang sama, maka Anda bisa mendapatkan semua dll yang Anda butuhkan di folder itu.

YantingChen
sumber
0

Pastikan bahwa dll dependen yang digunakan oleh Anda tidak memiliki target .net framework lebih tinggi dari target .net framework dari aplikasi proyek Anda.

Anda dapat memeriksa ini dengan memilih proyek Anda, lalu tekan ALT + ENTER, lalu pilih Aplikasi dari sisi kiri dan kemudian pilih Target Framework dari proyek Anda.

Misalkan, dependen dll Target Framework = 4.0 dan Application dll Target Framework = 3.5 kemudian ubah ke 4.0

Terima kasih!

Manish Jain
sumber
0

Selain yang umum di atas, saya punya solusi multi-proyek untuk diterbitkan. Rupanya beberapa file menargetkan kerangka kerja yang berbeda.

Jadi solusi saya: Properti> Versi Tertentu (Salah)

RicL
sumber
0

Tambahkan DLL sebagai item yang ada ke salah satu proyek dan harus diurutkan

abhijithkarkal
sumber
0

VS2019 V16.6.3

Bagi saya masalahnya adalah entah bagaimana file .proj utama berakhir dengan entri seperti ini untuk proyek yang DLLnya tidak disalin ke folder bin proyek induk:

<ProjectReference Include="Project B.csproj">
  <Project>{blah blah}</Project>
  <Name>Project B</Name>
  <Private>True</Private>
</ProjectReference>

Saya secara manual menghapus baris <Private>True</Private>dan DLL kemudian disalin ke folder bin proyek utama pada setiap build dari proyek utama.

Jika Anda pergi ke referensi proyek masalah di folder referensi proyek utama, klik dan lihat properti ada pengaturan "Salin Lokal". Tag pribadi sama dengan pengaturan ini, tetapi bagi saya untuk beberapa alasan mengubah salinan lokal tidak berpengaruh pada tag pribadi dalam file .proj.

Mengganggu saya tidak mengubah nilai salinan lokal untuk referensi, tidak tahu bagaimana itu bisa diatur seperti itu dan hari lain sia-sia melacak masalah bodoh dengan VS.

Terima kasih untuk semua jawaban lain yang membantu saya dalam menentukan penyebabnya.

HTH

Richard Moore
sumber