Menyematkan DLL dalam executable yang dikompilasi

619

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.

Merus
sumber
Saya akan merekomendasikan Anda memeriksa utilitas .NETZ, yang juga mengkompres perakitan dengan skema pilihan Anda: http://madebits.com/netz/help.php#single
Nathan Baulch
2
Itu mungkin, tetapi Anda akan berakhir dengan executable besar (Base64 akan digunakan untuk menyandikan dll Anda).
Paweł Dyda
Selain ILMerge , jika Anda tidak ingin repot dengan saklar baris perintah, saya sangat merekomendasikan ILMerge-Gui . Ini proyek open source, sangat bagus!
tyron
2
@ PawełDyda: Anda dapat menanamkan data biner mentah ke dalam gambar PE (lihat RCDATA ). Tidak diperlukan transformasi (atau direkomendasikan).
IInspectable

Jawaban:

761

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.

Install-Package Costura.Fody

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:

Install-CleanReferencesTarget

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 )

Matthias
sumber
79
Terima kasih atas saran yang luar biasa ini. Instal paket dan Anda selesai. Bahkan kompres majelis secara default.
Daniel
9
Benci menjadi 'saya juga', tetapi saya juga - ini menyelamatkan saya banyak sakit kepala! Terima kasih atas rekomendasinya! Ini memungkinkan saya untuk mengemas semua yang saya butuhkan untuk mendistribusikan kembali menjadi satu exe dan sekarang lebih kecil dari exe asli dan dll digabungkan ... Saya hanya menggunakan ini selama beberapa hari, jadi saya tidak bisa mengatakan bahwa saya ' Saya telah memasukkannya melalui langkah-langkahnya, tetapi mencegah sesuatu yang buruk muncul, saya bisa melihat ini menjadi alat biasa di kotak alat saya. Itu hanya bekerja!
mattezell
20
Itu keren. Tetapi ada kerugiannya: perakitan yang dihasilkan pada Windows tidak lagi biner kompatibel dengan mono Linux. Itu berarti, Anda tidak dapat menyebarkan perakitan ke Linux mono secara langsung.
Tyler Long
7
Ini indah! Jika Anda menggunakan vs2018 jangan lupa file FodyWeavers.xml berada di root proyek Anda.
Alan Deep
4
Sebagai pelengkap komentar terakhir: tambahkan FodyWeavers.xml dengan konten berikut ke proyek Anda: <? Xml version = "1.0" encoding = "utf-8"?> <Weavers VerifyAssembly = "true"> <Costura /> </Weavers>
HHenn
89

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 posting blog asli saya: http://codeblog.larsholm.net/2011/06/embed-dlls-easily-in-a-net-assembly/

Lars Holm Jensen
sumber
6
Anda dapat memiliki perilaku ini di luar kotak. Lihat jawaban saya stackoverflow.com/a/20306095/568266
Matthias
4
Juga penting untuk mencatat komentar yang sangat berguna di blog Anda dari AshRowe: jika Anda memiliki tema khusus yang diinstal, itu akan mencoba menyelesaikan perakitan PresentationFramework.Theme yang macet dan terbakar! Sesuai saran AshRowe, Anda cukup memeriksa apakah dllName berisi PresentationFramework seperti: if (dllName.ToLower (). Contains ("presentationframework")) mengembalikan null;
YasharBahman
4
Dua komentar tentang ini. Satu: Anda harus memeriksa apakah bytesitu 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.
Nyerguds
2
Kelebihan dari pendekatan ini adalah bahwa ia tidak mengandalkan menginstal lib eksternal untuk mencapai fungsi yang diinginkan. Kelemahan dari pendekatan ini adalah bahwa itu hanya berguna ketika datang ke dll dikelola - dll dll interop (setidaknya sejauh pengujian saya berjalan) tidak memecat assemblyresolve event dan bahkan jika mereka melakukan Assembly.Load (<byte dari beberapa interop .dll>) tidak mencapai efek yang diinginkan di jalan. stackoverflow.com/questions/13113131/... Hanya 2c saya tentang masalah ini
XDS
3
Untuk berjaga-jaga jika ada yang mengalami masalah saya: jika .dllnamanya berisi tanda hubung (yaitu twenty-two.dll), itu juga akan diganti dengan garis bawah (yaitu twenty_two.dll). Anda dapat mengubah baris kode ini menjadi ini:dllName = dllName.Replace(".", "_").Replace("-", "_");
Micah Vertal
87

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?

Shog9
sumber
Saya tertarik pada penggabungan DLL asli, apakah ada bahan?
Baiyan Huang
5
Lihat juga: stackoverflow.com/questions/108971/...
Milan Gardian
@BaiyanHuang lihat github.com/boxedapp/bxilmerge , idenya adalah membuat "ILMerge" untuk Dll asli.
Artem Razin
Pengembang VB NET seperti saya jangan takut dengan C++tautan itu. ILMerge juga bekerja dengan sangat mudah untuk VB NET. Lihat di sini https://github.com/dotnet/ILMerge . Terima kasih @ Shog9
Ivan Ferrer Villa
26

Ya, dimungkinkan untuk menggabungkan .NET yang dapat dieksekusi dengan perpustakaan. Ada beberapa alat yang tersedia untuk menyelesaikan pekerjaan:

  • ILMerge adalah utilitas yang dapat digunakan untuk menggabungkan banyak rakitan .NET menjadi satu rakitan.
  • Mono mkbundle , sebuah exe dan semua rakitan dengan libmono ke dalam satu paket biner.
  • IL-Repack adalah alternatif FLOSS untuk ILMerge, dengan beberapa fitur tambahan.

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.

.NETZ adalah alat sumber terbuka yang mengompresi dan mengemas file Microsoft .NET Framework yang dapat dieksekusi (EXE, DLL) untuk membuatnya lebih kecil.

Polisi
sumber
NETZ tampaknya hilang
Rbjz
Wow - saya pikir saya akhirnya menemukannya, lalu saya membaca komentar ini. Tampaknya sudah benar-benar hilang. Apakah ada garpu?
Mafii
Yah, itu baru saja pindah ke GitHub dan tidak lagi terhubung di situs web ... jadi "benar-benar hilang" adalah pernyataan yang berlebihan. Kemungkinan besar itu tidak didukung lagi, tetapi masih ada. Saya memperbarui tautan.
Bobby
20

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.

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 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:

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

    //or just

    return Assembly.LoadFrom(dllFullPath); //if location is known.

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

nawfal
sumber
Perhatikan bahwa "Aksi Bangun" Sumber Daya perlu diatur ke "Sumber Daya Tertanam".
Mavamaarten
@Mavamaarten Belum tentu. Jika ditambahkan ke Resources.resx proyek sebelumnya, Anda tidak perlu melakukan itu.
Nyerguds
2
EAZfuscator sekarang komersial.
Telemat
16

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).

AppDomain.CurrentDomain.AssemblyResolve += (sender, bargs) =>
        {
            String dllName = new AssemblyName(bargs.Name).Name + ".dll";
            var assem = Assembly.GetExecutingAssembly();
            String resourceName = assem.GetManifestResourceNames().FirstOrDefault(rn => rn.EndsWith(dllName));
            if (resourceName == null) return null; // Not found, maybe another handler will find it
            using (var stream = assem.GetManifestResourceStream(resourceName))
            {
                Byte[] assemblyData = new Byte[stream.Length];
                stream.Read(assemblyData, 0, assemblyData.Length);
                return Assembly.Load(assemblyData);
            }
        };
Steve
sumber
1
Mengubahnya sedikit, berhasil, tnx sobat!
Sean Ed-Man
Proyek libz.codeplex.com menggunakan proses ini tetapi akan melakukan beberapa hal lain juga seperti mengelola event handler untuk Anda dan beberapa kode khusus untuk tidak memecahkan " Katalog Kerangka Kerja Ekstensibilitas Terkelola " (yang dengan sendirinya proses ini akan rusak)
Scott Chamberlain
Itu keren!! Terima kasih @Steve
Ahmer Afzal
14

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.

  1. Instal paket nuget ILRepack.MSBuild.Task dengan Install-Package ILRepack.MSBuild.Task
  2. Edit bagian AfterBuild dari .csproj Anda

Berikut adalah contoh sederhana yang menggabungkan ExampleAssemblyToMerge.dll ke dalam output proyek Anda.

<!-- ILRepack -->
<Target Name="AfterBuild" Condition="'$(Configuration)' == 'Release'">

   <ItemGroup>
    <InputAssemblies Include="$(OutputPath)\$(AssemblyName).exe" />
    <InputAssemblies Include="$(OutputPath)\ExampleAssemblyToMerge.dll" />
   </ItemGroup>

   <ILRepack 
    Parallel="true"
    Internalize="true"
    InputAssemblies="@(InputAssemblies)"
    TargetKind="Exe"
    OutputFile="$(OutputPath)\$(AssemblyName).exe"
   />
</Target>
Josh
sumber
1
Sintaks untuk IL-Repack telah berubah, periksa README.md yang ada di repo github tertaut ( github.com/peters/ILRepack.MSBuild.Task ). Cara ini adalah satu-satunya yang bekerja untuk saya dan saya dapat menggunakan wildcard untuk mencocokkan semua dll yang ingin saya sertakan.
Seabass77
8

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).

MusiGenesis
sumber
Di sini Anda memiliki artikel hebat yang menjelaskan cara melakukannya: codeproject.com/Articles/528178/Load-DLL-Dari-Embedded-Resource
kebiruan
8

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.

Nathan
sumber
7

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:

Dictionary<string, Assembly> loaded = new Dictionary<string,Assembly>();
AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
{   Assembly resAssembly;
    string dllName = args.Name.Contains(",") ? args.Name.Substring(0, args.Name.IndexOf(',')) : args.Name.Replace(".dll","");
    dllName = dllName.Replace(".", "_");
    if ( !loaded.ContainsKey( dllName ) )
    {   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);
        resAssembly = System.Reflection.Assembly.Load(bytes);
        loaded.Add(dllName, resAssembly);
    }
    else
    {   resAssembly = loaded[dllName];  }
    return resAssembly;
};  

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:

static HashSet<string> IncludedAssemblies = new HashSet<string>();
string[] resources = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceNames();
for(int i = 0; i < resources.Length; i++)
{   IncludedAssemblies.Add(resources[i]);  }

dan hanya mengembalikan nol jika majelis yang lulus bukan milik IncludedAssemblies.

Ant_222
sumber
Maaf karena mempostingnya sebagai jawaban dan bukan sebagai komentar. Saya tidak punya hak untuk mengomentari jawaban orang lain.
Ant_222
5

.NET Core 3.0 secara alami mendukung kompilasi ke .exe tunggal

Fitur ini diaktifkan oleh penggunaan properti berikut di file proyek Anda (.csproj):

    <PropertyGroup>
        <PublishSingleFile>true</PublishSingleFile>
    </PropertyGroup>

Ini dilakukan tanpa alat eksternal.

Lihat jawaban saya untuk pertanyaan ini untuk perincian lebih lanjut.

Marcell Toth
sumber
3

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 .

Ivan Ferrer Villa
sumber
Windows sendiri memiliki alat serupa bernama iexpress. Ini tutorialnya
Ivan Ferrer Villa
2

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):

using System;
using Renci;//FOR THE SSH
using System.Net;//FOR THE ADDRESS TRANSLATION
using System.Reflection;//FOR THE Assembly

//+ref>"C:\Program Files (x86)\Microsoft\ILMerge\Renci.SshNet.dll"
//+res>"C:\Program Files (x86)\Microsoft\ILMerge\Renci.SshNet.dll"
//+ico>"C:\Program Files (x86)\Microsoft CAPICOM 2.1.0.2 SDK\Samples\c_sharp\xmldsig\resources\Traffic.ico"

Tag ref, res, dan ico akan diambil oleh skrip .vbs di bawah ini untuk membentuk perintah csc.

Kemudian tambahkan pemanggil resolver perakitan di Main:

public static void Main(string[] args)
{
    AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
    .

... dan tambahkan resolver itu sendiri di suatu tempat di kelas:

    static Assembly CurrentDomain_AssemblyResolve (pengirim objek, ResolveEventArgs args)
    {
        String resourceName = new AssemblyName (args.Name) .Name + ".dll";

        menggunakan (var stream = Assembly.GetExecutingAssembly (). GetManifestResourceStream (resourceName))
        {
            Byte [] assemblyData = Byte baru [stream.Length];
            stream.Baca (assemblyData, 0, assemblyData.Length);
            mengembalikan Assembly.Load (assemblyData);
        }

    }

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:

    Dim name_, oShell, fso
    Setel oShell = CreateObject ("Shell.Application")
    Set fso = CreateObject ("Scripting.fileSystemObject")

    MENGAMBIL NAMA SCRIPT VBS SEBAGAI NAMA FILE TARGET
    '#############################################
    name_ = Split (wscript.ScriptName, ".") (0)

    'DAPATKAN DLL EKSTERNAL DAN NAMA-NAMA ICON DARI FILE .CS
    '############################################## ######
    Const OPEN_FILE_FOR_READING = 1
    Setel objInputFile = fso.OpenTextFile (name_ & ".cs", 1)

    BACA SEGALA SESUATU DALAM ARRAY
    '############################
    inputData = Berpisah (objInputFile.ReadAll, vbNewline)

    Untuk setiap strData Dalam inputData

        jika dibiarkan (strData, 7) = "// + ref>" lalu 
            csc_references = csc_references & "/ reference:" & trim (ganti (strData, "// + ref>", "")) & ""
        berakhir jika

        jika dibiarkan (strData, 7) = "// + res>" lalu 
            csc_resources = csc_resources & "/ resource:" & trim (ganti (strData, "// + res>", "")) & ""
        berakhir jika

        jika dibiarkan (strData, 7) = "// + ico>" lalu 
            csc_icon = "/ win32icon:" & trim (ganti (strData, "// + ico>", "")) & ""
        berakhir jika
    Lanjut

    objInputFile.Close


    'Gabungkan FILE
    '#################
    oShell.ShellExecute "c: \ windows \ microsoft.net \ framework \ v3.5 \ csc.exe", "/ warnai: 1 / target: exe" & csc_references & csc_resources & csc_icon & "" & name_ & ".cs" , "", "runas", 2


    WScript.Quit (0)
Mark Llewellyn
sumber
0

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.

Chris Charabaruk
sumber
0

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).

tidak bisa
sumber
1
Eazfuscator hanya akan memanggil IlMerge, AFAIK.
Bobby
+1 Bobby. Seharusnya aku ingat itu. Tentang semua yang dilakukan Eazfucator untuk Anda adalah abstrak dari panggilan sebenarnya ke ILMerge dengan file konfigurasi yang lebih umum.
wllmsaccnt