Wie kann eine C ++ Windows-DLL in eine C # Anwendung exe zusammengeführt werden?

StackOverflow https://stackoverflow.com/questions/72264

  •  09-06-2019
  •  | 
  •  

Frage

Ich habe ein Windows-C # Programm, das eine C ++ DLL für Daten verwendet, i / o. Mein Ziel ist es, die Anwendung als einzelne EXE zu implementieren.

Was sind die Schritte, wie eine ausführbare Datei zu erstellen?

War es hilfreich?

Lösung

Single Assembly Bereitstellung von Managed und Unmanaged-Code Sonntag 4. Februar; 2007

.NET-Entwickler lieben XCOPY-Bereitstellung. Und sie lieben einzelnen Baugruppenkomponenten. Zumindest fühle ich mich immer ein bisschen unruhig, wenn ich einige Komponenten verwenden und müssen eine Liste von Dateien erinnern, auch mit der Hauptbaugruppe dieser Komponente enthalten. Also, wenn ich vor kurzem einen verwalteten Code-Komponente entwickeln musste und hatte es mit einigen nicht verwalteten Code aus einer C-DLL (thx an Marcus Heege für mich mit diesem zu helfen!) Zu erweitern, dachte ich darüber nach, wie es einfacher zu machen, die beiden DLLs zu implementieren . Wenn dies nur zwei Baugruppen war ich ILMerge hätte verwendet, um sie in nur eine Datei zu packen. Aber dies nicht funktioniert für gemischte Codekomponenten mit sowie nicht verwaltete DLLs verwaltet werden.

So Heres, was ich kam mit einer Lösung:

I umfassen, was DLLs ich mit meiner component's Hauptbaugruppe als eingebettete Ressourcen bereitstellen möchten. Dann habe ich eine Klasse Konstruktor auf diese DLLs wie unten zu extrahieren. Die Klasse ctor wird nur einmal aufgerufen innerhalb jeder AppDomain also ist es eine vernachlässigbare Overhead, denke ich.

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

        ...

In diesem Beispiel enthalten ich zwei DLLs als Ressourcen, von denen eine einen nicht verwalteten Code-DLL, und man einen verwalteten Code DLL zu sein (nur zu Demonstrationszwecken), um zu zeigen, wie diese Technik für beide Arten von Code funktioniert.

Der Code, um den DLLs in Dateien der eigenen zu extrahieren ist einfach:

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

mit einer verwalteten Code-Anordnung Arbeiten wie das ist das gleiche wie üblich - fast. Sie verweisen sie (hier: ManagedService.dll) in Ihrem component's Hauptprojekt (hier: MyLib), aber die Copy Local Eigenschaft auf false gesetzt. Zusätzlich verknüpfen Sie bei der Montage als Vorhandenes Element und stellen Sie die Build Action auf Eingebettete Ressource.

Für den nicht verwalteten Code (hier: UnmanagedService.dll) verknüpfen Sie nur in der DLL als ein vorhandenes Element und stellen Sie die Build Action auf Eingebettete Ressource. Für den Zugriff auf Funktionen der DllImport Attribut verwenden wie üblich, z.

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

Das ist es! Sobald Sie die erste Instanz der Klasse mit dem statischen Ctor der eingebetteten DLLs in Dateien der eigenen bekommen extrahierten erstellen und sind sofort einsatzbereit, als ob Sie sie als separate Dateien im Einsatz. Solange Sie Schreibberechtigungen für das Ausführungsverzeichnis sollte dies für Sie funktionieren. Zumindest für prototypische Code denke ich, diese Art der einzigen Montage Einsatz sehr bequem ist.

Genießen Sie!

Andere Tipps

Versuchen Sie BoxedApp ; es lassen sich alle DLLs aus dem Speicher zu laden. Auch scheint es, dass Sie auch .net Laufzeit einbetten können. Gut eine wirklich eigenständige Anwendungen zu erstellen ...

Mit Fody.Costura nuget

  1. Öffnen Sie Ihre Lösung -> Projekt -> Manage Nuget Pakete
  2. Suchen Sie nach Fody.Costura
  3. Compile Ihre Projekt .

Das ist es!

  

Quelle:    http://www.manuelmeyer.net/2016 / 01 / netto-Leistung-tip-10-Fusion-Baugruppen /

Haben Sie ILMerge versucht? http://research.microsoft.com/~mbarnett/ILMerge.aspx

  

ILMerge ist ein Dienstprogramm, das verwendet werden kann mehrere .NET Baugruppen in einer einzigen Baugruppe zusammenzuführen. Es ist frei verfügbar für den Einsatz der Werkzeuge und Hilfsprogramme Seite auf der Microsoft .NET Framework Developer Center.

Wenn Sie die C ++ DLL mit dem /clr Flagge Gebäude sind (ganz oder teilweise C ++ / CLI), dann sollte es funktionieren:

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

Es wird jedoch nicht mit einem gewöhnlichen (nativ) Windows DLL arbeiten.

Einfach mit der rechten Maustaste auf Ihr Projekt in Visual Studio, wählen Sie Projekteigenschaften -> Ressourcen -> Ressource hinzufügen -> Vorhandene hinzufügen Datei ... Und schließen Sie den Code unten an deine App.xaml.cs oder gleichwertig.

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

Hier ist meine ursprüngliche Blog-Post: http://codeblog.larsholm.net/ 2011/06 / embed-dlls-leicht-in-a-net-Montage /

ThinApp ist eine Lösung. Für eine native Windows-Anwendung würde ich vorschlagen, die DLL als binäres Ressourcenobjekt einbetten, dann ist es zur Laufzeit zu extrahieren, bevor Sie sie brauchen.

Smart-Assembly kann dies und mehr tun. Wenn Ihr DLL nicht verwalteten Code hat, wird es nicht lassen Sie den DLLs zu einem einzigen Baugruppe zusammenführen, sondern kann die erforderlichen Abhängigkeiten als Ressourcen zu Ihrem Haupt-exe einbetten. Seine Kehrseite, es ist nicht frei.

Sie können diese DLL durch das Einbetten von Hand tun, um Ihre Ressourcen und dann auf AppDomain Versammlung ResolveHandler verlassen. Wenn es in dem gemischten Modus dlls kommt, fand ich viele der Varianten und Geschmacksrichtungen von ResolveHandler Ansatz nicht für mich zu arbeiten (alle, den dll Bytes in dem Speicher lesen und lesen daraus). Sie alle arbeiteten für verwaltete DLLs. Hier ist, was für mich gearbeitet:

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

Der Schlüssel hier ist der Bytes in eine Datei und lädt von seiner Lage zu schreiben. Um Huhn-Ei-Problem zu vermeiden, müssen Sie sicherstellen, dass Sie den Handler deklarieren vor der Montage den Zugriff auf und die Sie greifen nicht die Montageelemente (oder irgendetwas instanziiert, die mit der Montage zu tun hat) innerhalb des Lade (Montage Lösung) Teil. nehmen auch GetMyApplicationSpecificPath(), um sicherzustellen, ist nicht Tempverzeichnis da temporäre Dateien versucht werden könnte, um von anderen Programmen gelöscht zu bekommen oder selbst (nicht, dass es gelöscht werden, während Ihr Programm die DLL zugreifen, aber zumindest ist es ein Ärgernis. AppData ist gute Lage). Beachten Sie auch, dass Sie die Bytes jedes Mal zu schreiben, Sie kippe Last von Lage, nur ‚cos die DLL bereits dort wohnt.

Wenn die Assembly vollständig unmanaged ist, können Sie diese sehen Link oder this , wie solcher DLLs zu laden.

Xenocode verpacken können beide verwaltet und unmanged in einer einzigen EXE-Datei.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top