Apakah mungkin untuk menanamkan DLL yang sudah ada ke dalam executable C # yang dikompilasi (sehingga Anda hanya memiliki satu file untuk didistribusikan)? Jika mungkin, bagaimana cara melakukannya?
Biasanya, saya keren dengan hanya meninggalkan DLL di luar dan memiliki program setup menangani semuanya, tetapi ada beberapa orang di tempat kerja yang bertanya kepada saya dan saya benar-benar tidak tahu.
Jawaban:
Saya sangat merekomendasikan untuk menggunakan Costura.Fody - sejauh ini cara terbaik dan termudah untuk menanamkan sumber daya dalam perakitan Anda. Ini tersedia sebagai paket NuGet.
Setelah menambahkannya ke proyek, itu akan secara otomatis menanamkan semua referensi yang disalin ke direktori output ke dalam perakitan utama Anda . Anda mungkin ingin membersihkan file yang disematkan dengan menambahkan target ke proyek Anda:
Anda juga dapat menentukan apakah akan menyertakan pdb, mengecualikan rakitan tertentu, atau mengekstraksi rakitan dengan cepat. Sejauh yang saya tahu, majelis yang tidak dikelola juga didukung.
Memperbarui
Saat ini, beberapa orang mencoba menambahkan dukungan untuk DNX .
Perbarui 2
Untuk versi Fody terbaru, Anda harus memiliki MSBuild 16 (jadi Visual Studio 2019). Fody versi 4.2.1 akan melakukan MSBuild 15. (referensi: Fody hanya didukung pada MSBuild 16 ke atas. Versi saat ini: 15 )
sumber
Cukup klik kanan proyek Anda di Visual Studio, pilih Properti Proyek -> Sumber Daya -> Tambahkan Sumber Daya -> Tambahkan File yang Ada ... Dan masukkan kode di bawah ini ke App.xaml.cs Anda atau yang setara.
Inilah posting blog asli saya: http://codeblog.larsholm.net/2011/06/embed-dlls-easily-in-a-net-assembly/
sumber
bytes
itu nol, dan jika demikian, kembalikan nol di sana. Mungkin saja dll tidak ada dalam sumber daya. Dua: Ini hanya berfungsi jika kelas itu sendiri tidak memiliki "penggunaan" untuk apa pun dari majelis itu. Untuk alat-alat baris perintah, saya harus memindahkan kode program saya yang sebenarnya ke file baru, dan membuat program utama kecil baru yang hanya melakukan ini dan kemudian memanggil utama asli di kelas lama..dll
namanya berisi tanda hubung (yaitutwenty-two.dll
), itu juga akan diganti dengan garis bawah (yaitutwenty_two.dll
). Anda dapat mengubah baris kode ini menjadi ini:dllName = dllName.Replace(".", "_").Replace("-", "_");
Jika mereka benar-benar dikelola rakitan, Anda dapat menggunakan ILMerge . Untuk DLL asli, Anda akan memiliki sedikit pekerjaan yang harus dilakukan.
Lihat juga: Bagaimana C ++ windows dll dapat digabungkan ke dalam aplikasi C # exe?
sumber
C++
tautan itu. ILMerge juga bekerja dengan sangat mudah untuk VB NET. Lihat di sini https://github.com/dotnet/ILMerge . Terima kasih @ Shog9Ya, dimungkinkan untuk menggabungkan .NET yang dapat dieksekusi dengan perpustakaan. Ada beberapa alat yang tersedia untuk menyelesaikan pekerjaan:
Selain itu, ini dapat dikombinasikan dengan Mono Linker , yang menghapus kode yang tidak digunakan dan karenanya membuat perakitan yang dihasilkan lebih kecil.
Kemungkinan lain adalah dengan menggunakan .NETZ , yang tidak hanya memungkinkan kompres suatu rakitan, tetapi juga dapat mengemas dll langsung ke exe. Perbedaannya dengan solusi yang disebutkan di atas adalah bahwa. NETZ tidak menggabungkan mereka, mereka tetap rakitan terpisah tetapi dikemas dalam satu paket.
sumber
ILMerge dapat menggabungkan rakitan ke satu rakitan tunggal asalkan rakitan hanya memiliki kode yang dikelola. Anda dapat menggunakan aplikasi commandline, atau menambahkan referensi ke exe dan secara terprogram bergabung. Untuk versi GUI ada Eazfuscator , dan juga .Netz yang keduanya gratis. Aplikasi berbayar termasuk BoxedApp dan SmartAssembly .
Jika Anda harus menggabungkan rakitan dengan kode yang tidak dikelola, saya akan menyarankan SmartAssembly . Saya tidak pernah mengalami cegukan dengan SmartAssembly tetapi dengan yang lainnya. Di sini, ia dapat menanamkan dependensi yang diperlukan sebagai sumber daya ke exe utama Anda.
Anda dapat melakukan semua ini secara manual tidak perlu khawatir jika perakitan dikelola atau dalam mode campuran dengan menyematkan dll ke sumber daya Anda dan kemudian mengandalkan Majelis AppDomain
ResolveHandler
. Ini adalah solusi satu atap dengan mengadopsi kasus terburuk, yaitu rakitan dengan kode yang tidak dikelola.Kuncinya di sini adalah untuk menulis byte ke file dan memuat dari lokasinya. Untuk menghindari masalah ayam dan telur, Anda harus memastikan bahwa Anda menyatakan pawang sebelum mengakses rakitan dan bahwa Anda tidak mengakses anggota rakitan (atau instantiate apa pun yang harus berurusan dengan rakitan) di dalam bagian pemuatan (penyelesaian rakitan). Juga berhati-hatilah untuk memastikan
GetMyApplicationSpecificPath()
tidak ada direktori temp karena file temp dapat diupayakan dihapus oleh program lain atau oleh Anda sendiri (bukan berarti ia akan dihapus ketika program Anda mengakses dll, tetapi setidaknya itu gangguan. AppData baik) lokasi). Juga perhatikan bahwa Anda harus menulis byte setiap kali, Anda tidak dapat memuat dari lokasi hanya karena dll sudah ada di sana.Untuk dll yang dikelola, Anda tidak perlu menulis byte, tetapi langsung memuat dari lokasi dll, atau hanya membaca byte dan memuat perakitan dari memori. Seperti ini atau lebih:
Jika perakitan sepenuhnya tidak dikelola, Anda dapat melihat tautan ini atau ini tentang cara memuat dll.
sumber
The kutipan oleh Jeffrey Richter sangat baik. Singkatnya, tambahkan perpustakaan sebagai sumber daya yang disematkan dan tambahkan panggilan balik sebelum hal lain. Berikut ini adalah versi kode (ditemukan di komentar halamannya) yang saya letakkan di awal metode Utama untuk aplikasi konsol (pastikan saja panggilan yang menggunakan perpustakaan menggunakan metode yang berbeda dengan Utama).
sumber
Untuk memperluas pada asnwer @ Bobby di atas. Anda dapat mengedit .csproj Anda untuk menggunakan IL-Repack untuk secara otomatis mengemas semua file menjadi satu rakitan ketika Anda membangun.
Install-Package ILRepack.MSBuild.Task
Berikut adalah contoh sederhana yang menggabungkan ExampleAssemblyToMerge.dll ke dalam output proyek Anda.
sumber
Anda bisa menambahkan DLL sebagai sumber daya yang disematkan, dan kemudian minta program Anda membongkar mereka ke direktori aplikasi pada startup (setelah memeriksa untuk melihat apakah mereka sudah ada di sana).
Setup file sangat mudah dibuat, meskipun, saya tidak berpikir ini akan sia-sia.
EDIT: Teknik ini akan mudah dengan majelis .NET. Dengan DLL non-.NET akan jauh lebih banyak pekerjaan (Anda harus mencari tahu di mana harus membongkar file dan mendaftarkannya dan sebagainya).
sumber
Produk lain yang dapat menangani ini dengan elegan adalah SmartAssembly, di SmartAssembly.com . Produk ini akan, selain menggabungkan semua dependensi menjadi satu DLL, (opsional) mengaburkan kode Anda, menghapus meta-data tambahan untuk mengurangi ukuran file yang dihasilkan, dan juga dapat benar-benar mengoptimalkan IL untuk meningkatkan kinerja runtime.
Ada juga beberapa jenis fitur penanganan / pelaporan pengecualian global yang ditambahkannya ke perangkat lunak Anda (jika diinginkan) yang dapat berguna. Saya percaya ini juga memiliki API baris perintah sehingga Anda dapat menjadikannya bagian dari proses pembuatan Anda.
sumber
Baik pendekatan ILMerge maupun Lars Holm Jensen yang menangani acara AssemblyResolve tidak akan berfungsi untuk host plugin. Katakanlah H dapat dieksekusi, rakitan P secara dinamis dan mengaksesnya melalui antarmuka IP yang ditentukan dalam rakitan terpisah. Untuk menanamkan IP ke dalam H, seseorang perlu sedikit modifikasi pada kode Lars:
Trik untuk menangani upaya berulang untuk menyelesaikan rakitan yang sama dan mengembalikan yang sudah ada alih-alih membuat contoh baru.
EDIT: Jangan sampai merusak. Serialisasi NET, pastikan untuk mengembalikan null untuk semua majelis yang tidak tertanam dalam Anda, sehingga default ke perilaku standar. Anda bisa mendapatkan daftar perpustakaan ini dengan:
dan hanya mengembalikan nol jika majelis yang lulus bukan milik
IncludedAssemblies
.sumber
.NET Core 3.0 secara alami mendukung kompilasi ke .exe tunggal
Fitur ini diaktifkan oleh penggunaan properti berikut di file proyek Anda (.csproj):
Ini dilakukan tanpa alat eksternal.
Lihat jawaban saya untuk pertanyaan ini untuk perincian lebih lanjut.
sumber
Ini mungkin terdengar sederhana, tetapi WinRar memberikan opsi untuk mengompres banyak file ke file yang dapat dieksekusi.
Ini memiliki banyak opsi yang dapat dikonfigurasi: ikon terakhir, ekstrak file ke jalur yang diberikan, file untuk dieksekusi setelah ekstraksi, logo / teks khusus untuk popup yang ditampilkan selama ekstraksi, tidak ada jendela sembulan sama sekali, teks perjanjian lisensi, dll.
Mungkin bermanfaat dalam beberapa kasus .
sumber
Saya menggunakan kompiler csc.exe yang dipanggil dari skrip .vbs.
Dalam skrip xyz.cs Anda, tambahkan baris berikut setelah arahan (contoh saya adalah untuk Renci SSH):
Tag ref, res, dan ico akan diambil oleh skrip .vbs di bawah ini untuk membentuk perintah csc.
Kemudian tambahkan pemanggil resolver perakitan di Main:
... dan tambahkan resolver itu sendiri di suatu tempat di kelas:
Saya beri nama skrip vbs agar sesuai dengan nama file .cs (mis. Ssh.vbs mencari ssh.cs); ini membuat menjalankan skrip berkali-kali jauh lebih mudah, tetapi jika Anda bukan idiot seperti saya maka skrip generik dapat mengambil file .cs target dari drag-and-drop:
sumber
Sangat mungkin tetapi tidak semudah itu, untuk membuat perakitan hybrid asli / terkelola dalam C #. Apakah Anda menggunakan C ++ sebagai gantinya akan jauh lebih mudah, karena kompiler Visual C ++ dapat membuat rakitan hybrid semudah apa pun.
Kecuali Anda memiliki persyaratan ketat untuk menghasilkan perakitan hibrida, saya setuju dengan MusiGenesis bahwa ini tidak sepadan dengan kesulitan yang harus dilakukan dengan C #. Jika Anda perlu melakukannya, mungkin lebih baik Anda beralih ke C ++ / CLI.
sumber
Secara umum Anda akan memerlukan beberapa bentuk alat membangun pos untuk melakukan gabungan perakitan seperti yang Anda gambarkan. Ada alat gratis bernama Eazfuscator (eazfuscator.blogspot.com/) yang dirancang untuk bytecode mangling yang juga menangani penggabungan perakitan. Anda bisa menambahkan ini ke dalam baris perintah post build dengan Visual Studio untuk menggabungkan majelis Anda, tetapi jarak tempuh Anda akan bervariasi karena masalah yang akan muncul dalam skenario penggabungan perakitan non-trival.
Anda juga dapat memeriksa untuk melihat apakah build yang membuat NANT memiliki kemampuan untuk menggabungkan rakitan setelah membangun, tetapi saya sendiri tidak cukup terbiasa dengan NANT untuk mengatakan apakah fungsionalitasnya dibangun atau tidak.
Ada juga banyak banyak plugin Visual Studio yang akan melakukan penggabungan perakitan sebagai bagian dari membangun aplikasi.
Atau jika Anda tidak perlu melakukan ini secara otomatis, ada sejumlah alat seperti ILMerge yang akan menggabungkan rakitan .net menjadi satu file.
Masalah terbesar yang saya miliki dengan menggabungkan majelis adalah jika mereka menggunakan ruang nama yang serupa. Atau lebih buruk, referensi berbagai versi dll yang sama (masalah saya umumnya dengan file dll NUnit).
sumber