it-swarm-eu.dev

Jak lze c ++ windows dll sloučit do exe aplikace C #?

Mám Windows C # program, který používá C++ dll pro data i/o. Mým cílem je nasadit aplikaci jako jeden EXE.

Jaké jsou kroky k vytvoření takového spustitelného souboru?

32
Noah

Zavedení řízeného a nespravovaného kódu Neděle, 4. února 2007

.NET vývojáři milují nasazení XCOPY. A milují jednotlivé komponenty shromáždění. Přinejmenším se vždy cítím trochu nesvůj, když musím použít nějakou komponentu a potřebovat si zapamatovat seznam souborů, které mají být také součástí hlavního shromáždění této komponenty. Takže když jsem nedávno musel vyvinout spravovanou komponentu kódu a musel jsem ji rozšířit o nějaký nespravovaný kód z C DLL (thx na Marcus Heege za to, že mi s tím pomohl!), Přemýšlel jsem o tom, jak to udělat jednodušší nasazení dvou knihoven DLL. Kdyby to byly jen dvě sestavy, mohl jsem použít ILmerge, aby je zabalil do jednoho souboru. To ale nefunguje pro smíšené komponenty kódu s řízenými i nespravovanými knihovnami DLL.

Tady je to, co jsem přišel s řešením:

Zahrnuji cokoliv, co chci rozmístit s mým hlavním shromážděním jako vložené zdroje. Pak jsem nastavil konstruktor tříd, abych extrahoval tyto knihovny jako níže. Třída ctor je volána jen jednou v rámci každého AppDomainu, takže myslím, že je to zbytečná režie.

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

        ...

V tomto příkladu jsem jako zdroje zahrnula dvě knihovny DLL, přičemž jedna z nich byla neřízená kódová knihovna DLL a jedna byla spravovaným kódem DLL (pouze pro účely demonstrace), aby ukázala, jak tato technika funguje pro oba druhy kódu.

Kód pro extrahování knihoven DLL do vlastních souborů je jednoduchý:

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);
                }
    }
}

Práce s takto spravovaným kódem je stejná jako obvykle - téměř. Odkazujete na něj (zde: ManagedService.dll) v hlavním projektu komponenty (zde: MyLib), ale nastavte vlastnost Kopírovat místní na hodnotu false. Navíc se připojujete k sestavě jako existující položka a nastavíte akci Sestavit na vložený zdroj.

Pro nespravovaný kód (zde: UnmanagedService.dll) stačí odkazovat na DLL jako existující položku a nastavit akci Build to Embedded Resource. Pro přístup ke svým funkcím použijte atribut DllImport jako obvykle, např.

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

A je to! Jakmile vytvoříte první instanci třídy se statickým ctor, vložené knihovny DLL se extrahují do vlastních souborů a jsou připraveny k použití, jako by byly nasazeny jako samostatné soubory. Pokud máte oprávnění k zápisu do adresáře pro provádění, mělo by to fungovat dobře. Přinejmenším pro prototypový kód si myslím, že tento způsob nasazení jediného shromáždění je docela pohodlný.

Užívat si!

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

16
Nick

Vyzkoušejte boxedapp ; umožňuje načíst všechny DLL z paměti. Také se zdá, že můžete dokonce vložit .net runtime. Je dobré vytvořit opravdu samostatné aplikace ...

3
Art

Klikněte pravým tlačítkem myši na váš projekt v aplikaci Visual Studio, vyberte položku Vlastnosti projektu -> Zdroje -> Přidat zdroj -> Přidat existující soubor… A zahrňte níže uvedený kód do souboru App.xaml.cs nebo jeho ekvivalentu.

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);
}

Zde je můj původní příspěvek na blogu: http://codeblog.larsholm.net/2011/06/embed-dlls-easily-in-a-net-Assembly/

1
Lars Holm Jensen

Použít Fody.Costura nuget

  1. Otevřete své řešení -> Project -> Manage Nuget Packages
  2. Hledat Fody.Costura
  3. Compile your project

A je to !

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

1
automan

Vyzkoušeli jste ILMerge? http://research.Microsoft.com/~mbarnett/ILMerge.aspx

ILMerge je nástroj, který lze použít ke sloučení více sestav .NET do jednoho sestavení. Je volně dostupný pro použití na stránce Nástroje a nástroje na vývojovém centru Microsoft .NET Framework. 

Pokud vytváříte C++ DLL s příznakem /clr (vše nebo částečně C++/CLI), pak by mělo fungovat:

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

Nebude však fungovat s běžným (nativním) Windows DLL. 

1
Raithlin

Inteligentní shromáždění to může udělat a další. Pokud vaše dll má nespravovaný kód, je zvyklý nechat sloučit dlls do jednoho shromáždění, místo toho může vložit požadované závislosti jako zdroje do vašeho hlavního exe. Jeho flip-side, není to zdarma.

Můžete to provést ručně vložením dll do svých zdrojů a poté spoléháním na sestavu AppDomain ResolveHandler. Když přijde na smíšený režim dlls, našel jsem mnoho variant a chutí ResolveHandler přístupu, aby nepracovaly pro mě (všechny, které čtou dll bajty do paměti a čtou z ní). Všichni pracovali pro řízené dll. Zde je to, co pro mě fungovalo:

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);
    };
}

Klíčem je zde zapsat bajty do souboru a načíst ze svého umístění. Abyste se vyhnuli problému s kuřecím masem a vajíčkem, musíte před vstupem do shromáždění zajistit, abyste před zahájením montáže prohlásili psovoda a abyste se nedostali k členům shromáždění (nebo vytvořte něco, co by se muselo zabývat shromážděním) uvnitř části, která je určena pro vkládání. Také dbejte na to, aby GetMyApplicationSpecificPath() nebyl žádný temp adresář, protože temp soubory by mohly být pokoušeny dostat vymazány jinými programy nebo sami (ne že to bude odstraněn, zatímco váš program je přístup k DLL, ale alespoň jeho obtíže. AppData je dobré umístění). Všimněte si také, že pokaždé musíte zapsat bajty, nemůžete načíst z místa jen 'protože dll již tam sídlí.

Pokud je Shromáždění zcela nespravováno, můžete vidět toto link nebo toto , jak načíst takové dll.

0
nawfal

Thinstall je jedno řešení. Pro nativní aplikaci Windows bych doporučil vložit objekt DLL jako objekt binárního zdroje a poté jej extrahovat za běhu, než jej budete potřebovat.

0
titanae