pengembangan-web-mp-pd.com

Bagaimana C++ windows dll dapat digabungkan menjadi aplikasi exe C #?

Saya memiliki program Windows C # yang menggunakan C++ dll untuk data i/o. Tujuan saya adalah untuk menyebarkan aplikasi sebagai EXE tunggal.

Apa langkah-langkah untuk membuat executable seperti itu?

32
Noah

Single Assembly Deployment dari Kode yang Dikelola dan Terkelola Minggu, 4 Februari 2007

Pengembang .NET menyukai penerapan XCOPY. Dan mereka suka komponen Majelis tunggal. Setidaknya saya selalu merasa agak tidak nyaman, jika saya harus menggunakan beberapa komponen dan perlu mengingat daftar file yang akan disertakan dengan Majelis utama komponen itu. Jadi ketika saya baru-baru ini harus mengembangkan komponen kode yang dikelola dan harus menambahnya dengan beberapa kode yang tidak dikelola dari C DLL (thx ke Marcus Heege karena membantu saya dengan ini!), Saya berpikir tentang cara membuatnya lebih mudah untuk menggunakan dua DLL. Jika ini hanya dua majelis saya bisa menggunakan ILmerge untuk mengemasnya hanya dalam satu file. Tapi ini tidak berfungsi untuk komponen kode campuran dengan DLL yang dikelola dan tidak dikelola.

Jadi, inilah yang saya cari solusinya:

Saya menyertakan DLL apa pun yang ingin saya gunakan dengan Majelis utama komponen saya sebagai sumber daya yang disematkan. Kemudian saya menyiapkan konstruktor kelas untuk mengekstrak DLL seperti di bawah ini. Ctor kelas disebut hanya sekali dalam setiap AppDomain sehingga merupakan biaya overhead yang diabaikan, saya pikir.

namespace MyLib
{
    public class MyClass
    {
        static MyClass()
        {
            ResourceExtractor.ExtractResourceToFile("MyLib.ManagedService.dll", "managedservice.dll");
            ResourceExtractor.ExtractResourceToFile("MyLib.UnmanagedService.dll", "unmanagedservice.dll");
        }

        ...

Dalam contoh ini saya menyertakan dua DLL sebagai sumber daya, satu menjadi kode DLL yang tidak dikelola, dan satu lagi menjadi kode yang dikelola DLL (hanya untuk tujuan demonstrasi), untuk menunjukkan, bagaimana teknik ini bekerja untuk kedua jenis kode.

Kode untuk mengekstrak DLL ke dalam file mereka sendiri sederhana:

public static class ResourceExtractor
{
    public static void ExtractResourceToFile(string resourceName, string filename)
    {
        if (!System.IO.File.Exists(filename))
            using (System.IO.Stream s = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName))
                using (System.IO.FileStream fs = new System.IO.FileStream(filename, System.IO.FileMode.Create))
                {
                    byte[] b = new byte[s.Length];
                    s.Read(b, 0, b.Length);
                    fs.Write(b, 0, b.Length);
                }
    }
}

Bekerja dengan Majelis kode yang dikelola seperti ini sama seperti biasanya - hampir. Anda merujuknya (di sini: ManagedService.dll) di proyek utama komponen Anda (di sini: MyLib), tetapi setel properti Salin Lokal ke false. Selain itu, Anda menautkan dalam Majelis sebagai Item yang Ada dan mengatur Tindakan Bangun ke Sumber Daya Tertanam.

Untuk kode yang tidak dikelola (di sini: UnmanagedService.dll) Anda cukup menautkan DLL sebagai Item yang Ada dan mengatur Build Action ke Sumber Daya yang Disematkan. Untuk mengakses fungsinya gunakan atribut DllImport seperti biasa, mis.

[DllImport("unmanagedservice.dll")] public extern static int Add(int a, int b);

Itu dia! Segera setelah Anda membuat instance pertama dari kelas dengan ctor statis, DLL tertanam dapat diekstraksi ke file mereka sendiri dan siap digunakan seolah-olah Anda menempatkan mereka sebagai file terpisah. Selama Anda memiliki izin menulis untuk direktori eksekusi, ini akan berfungsi dengan baik untuk Anda. Setidaknya untuk kode prototipe saya pikir cara pemasangan Majelis tunggal ini cukup nyaman.

Nikmati!

http://weblogs.asp.net/ralfw/archive/2007/02/04/single-Assembly-deployment-of-managed-and-unmanaged-code.aspx

16
Nick

Coba boxedapp ; memungkinkan untuk memuat semua DLL dari memori. Juga, tampaknya Anda bahkan dapat menanamkan .net runtime. Bagus untuk membuat aplikasi yang benar-benar mandiri ...

3
Art

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.

public App()
{
    AppDomain.CurrentDomain.AssemblyResolve +=new ResolveEventHandler(CurrentDomain_AssemblyResolve);
}

System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
    string dllName = args.Name.Contains(',') ? args.Name.Substring(0, args.Name.IndexOf(',')) : args.Name.Replace(".dll","");

    dllName = dllName.Replace(".", "_");

    if (dllName.EndsWith("_resources")) return null;

    System.Resources.ResourceManager rm = new System.Resources.ResourceManager(GetType().Namespace + ".Properties.Resources", System.Reflection.Assembly.GetExecutingAssembly());

    byte[] bytes = (byte[])rm.GetObject(dllName);

    return System.Reflection.Assembly.Load(bytes);
}

Inilah postingan blog asli saya: http://codeblog.larsholm.net/2011/06/embed-dlls- dengan mudah-in-a-net-Assembly/

1
Lars Holm Jensen

Gunakan Fody.Costura nuget

  1. Buka solusi Anda -> Proyek -> Kelola Paket Nuget
  2. Cari Fody.Costura
  3. Kompilasi your proyek

Itu dia !

Sumber: http://www.manuelmeyer.net/2016/01/net-power-tip-10-merging-assemblies/

1
automan

Sudahkah Anda mencoba ILMerge? http://research.Microsoft.com/~mbarnett/ILMerge.aspx

ILMerge adalah utilitas yang dapat digunakan untuk menggabungkan banyak rakitan .NET menjadi satu rakitan. Ini tersedia secara bebas untuk digunakan dari halaman Tools & Utilities di Pusat Pengembang Microsoft .NET Framework. 

Jika Anda sedang membangun C++ DLL dengan flag /clr (semua atau sebagian C++/CLI), maka itu akan berfungsi:

ilmerge /out:Composite.exe MyMainApp.exe Utility.dll

Namun itu tidak akan berfungsi dengan Windows DLLbiasa (asli). 

1
Raithlin

Smart Assembly dapat melakukan ini dan banyak lagi. Jika dll Anda memiliki kode yang tidak dikelola, dll tidak akan membiarkan Anda menggabungkan dll ke satu Majelis, sebagai gantinya dapat menanamkan dependensi yang diperlukan sebagai sumber daya ke exe utama Anda. Sisi lainnya, tidak gratis.

Anda dapat melakukan ini secara manual dengan menanamkan dll ke sumber daya Anda dan kemudian mengandalkan Majelis AppDomain ResolveHandler. Ketika datang ke mode campuran dll, saya menemukan banyak varian dan rasa dari ResolveHandler untuk tidak bekerja untuk saya (semua yang membaca byte dll ke memori dan membaca dari itu). Mereka semua bekerja untuk dll yang dikelola. Inilah yang bekerja untuk saya:

static void Main()
{
    AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
    {
        string assemblyName = new AssemblyName(args.Name).Name;
        if (assemblyName.EndsWith(".resources"))
            return null;

        string dllName = assemblyName + ".dll";
        string dllFullPath = Path.Combine(GetMyApplicationSpecificPath(), dllName);

        using (Stream s = Assembly.GetEntryAssembly().GetManifestResourceStream(typeof(Program).Namespace + ".Resources." + dllName))
        {
            byte[] data = new byte[stream.Length];
            s.Read(data, 0, data.Length);

            //or just byte[] data = new BinaryReader(s).ReadBytes((int)s.Length);

            File.WriteAllBytes(dllFullPath, data);
        }

        return Assembly.LoadFrom(dllFullPath);
    };
}

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 Majelis dan bahwa Anda tidak mengakses anggota Majelis (atau instantiate apa pun yang harus berurusan dengan Majelis) di dalam bagian pemuatan (penyelesaian Dewan). Juga berhati-hati untuk memastikan GetMyApplicationSpecificPath() bukan direktori temp karena file temp dapat dicoba dihapus oleh program lain atau oleh Anda sendiri (bukan berarti akan dihapus saat program Anda mengakses dll, tetapi setidaknya itu gangguan. lokasi yang bagus). Juga perhatikan bahwa Anda harus menulis byte setiap kali, Anda tidak dapat memuat dari lokasi hanya karena dll sudah ada di sana.

Jika Majelis sepenuhnya tidak dikelola, Anda dapat melihat ini tautan atau ini tentang cara memuat dll.

0
nawfal

Instal adalah salah satu solusi. Untuk aplikasi windows asli saya akan menyarankan menanamkan DLL sebagai objek sumber daya biner, kemudian mengekstraknya saat runtime sebelum Anda membutuhkannya.

0
titanae