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

Ich habe ein Windows C # -Programm, das eine C ++ – DLL für Daten-I / O verwendet. Mein Ziel ist es, die Anwendung als eine einzige EXE bereitzustellen.

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

Single Assembly Bereitstellung von verwaltetem und nicht verwaltetem Code Sonntag, 4. Februar 2007

.NET-Entwickler lieben die XCOPY-Bereitstellung. Und sie lieben einzelne assemblykomponenten. Zumindest fühle ich mich immer irgendwie unwohl, wenn ich irgendeine Komponente verwenden muss und eine Liste von Dateien behalten muss, die auch mit der Hauptbaugruppe dieser Komponente enthalten sein sollen. Als ich vor kurzem eine verwaltete Code-Komponente entwickeln musste und sie mit etwas nicht verwaltetem Code aus einer C-DLL erweitern musste (danke an Marcus Heege, der mir dabei geholfen hat!), Habe ich darüber nachgedacht, wie man die beiden DLLs einfacher bereitstellen kann . Wenn das nur zwei Assemblies wären, hätte ich ILmerge verwenden können, um sie in nur einer Datei zu packen. Dies funktioniert jedoch nicht für gemischte Code-Komponenten mit verwalteten und nicht verwalteten DLLs.

Also hier ist, was ich für eine Lösung gefunden habe:

Ich schließe alle DLLs ein, die ich mit der Hauptbaugruppe meiner Komponente als eingebettete Ressourcen bereitstellen möchte. Dann richte ich einen classnkonstruktor ein, um diese DLLs wie unten zu extrahieren. Die class ctor wird nur einmal in jeder AppDomain aufgerufen, also ist es ein vernachlässigbarer 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 habe ich zwei DLLs als Ressourcen eingefügt, eine davon ist eine DLL für nicht verwalteten Code und eine DLL für verwalteten Code (nur zu Demonstrationszwecken), um zu zeigen, wie diese Technik für beide Arten von Code funktioniert.

Der Code zum Extrahieren der DLLs in eigene Dateien 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); } } } 

Das Arbeiten mit einer verwalteten Code-Assembly ist wie gewohnt – fast. Sie referenzieren es (hier: ManagedService.dll) im Hauptprojekt Ihrer Komponente (hier: MyLib), setzen aber die Eigenschaft Copy Local auf false. Darüber hinaus verknüpfen Sie in der Assembly als ein vorhandenes Element und legen die Buildaktion auf eingebettete Ressource fest.

Für den nicht verwalteten Code (hier: UnmanagedService.dll) verknüpfen Sie einfach die DLL als ein vorhandenes Element und legen die Build-Aktion auf die eingebettete Ressource fest. Um auf seine functionen zuzugreifen, verwenden Sie wie üblich das DllImport-Attribut, z

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

Das ist es! Sobald Sie die erste Instanz der class mit dem statischen ctor erstellen, werden die eingebetteten DLLs in eigene Dateien extrahiert und können sofort verwendet werden, als würden Sie sie als separate Dateien bereitstellen. Solange Sie Schreibrechte für das Ausführungsverzeichnis haben, sollte dies für Sie gut funktionieren. Zumindest für prototypischen Code denke ich, dass diese Art der Bereitstellung einzelner Baugruppen recht praktisch ist.

Genießen!

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

Versuchen Sie boxedapp ; Es ermöglicht das Laden aller DLLs aus dem Speicher. Es scheint auch, dass Sie sogar .NET-Laufzeitumgebung einbetten können. Gut, um wirklich eigenständige Anwendungen zu erstellen …

Hast du ILMerge ausprobiert? http://research.microsoft.com/~mbarnett/ILMerge.aspx

ILMerge ist ein Dienstprogramm, mit dem mehrere .NET-Assemblies zu einer einzelnen Assembly zusammengeführt werden können. Es steht auf der Seite Tools & Utilities des Microsoft .NET Framework Developer Center zur freien Verfügung.

Wenn Sie die C ++ – DLL mit dem Flag /clr (ganz oder teilweise C ++ / CLI) /clr , sollte es funktionieren:

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

Es wird jedoch nicht mit einer normalen (nativen) Windows DLL funktionieren.

Klicken Sie einfach mit der rechten Maustaste auf Ihr Projekt in Visual Studio, wählen Sie Projekteigenschaften -> Ressourcen -> Ressource hinzufügen -> Vorhandene Datei hinzufügen … und fügen Sie den folgenden Code in Ihre App.xaml.cs oder gleichwertig ein.

 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 mein ursprünglicher Blog-Beitrag: http://codeblog.larsmol.net.net/06/embed-dlls-easily-in-a-net-assembly/

Verwenden Sie Fody.Costura nugget

  1. Öffnen Sie Ihre Lösung -> Projekt -> Nuget-Pakete verwalten
  2. Suche nach Fody.Costura
  3. Kompilieren Sie Ihr Projekt .

Das ist es !

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

Thinstall ist eine Lösung. Für eine native Windows-Anwendung würde ich vorschlagen, die DLL als binäres Ressourcenobjekt einzubetten und sie dann zur Laufzeit zu extrahieren, bevor sie benötigt wird.

Smart Assembly kann dies und mehr. Wenn Ihre DLL über nicht verwalteten Code verfügt, können Sie die DLLs nicht zu einer einzelnen Assembly zusammenführen, sondern stattdessen die erforderlichen Abhängigkeiten als Ressourcen in die Haupt-EXE einbetten. Seine Rückseite ist nicht frei.

Sie können dies manuell tun, indem Sie dll in Ihre Ressourcen einbetten und sich dann auf den Assembly ResolveHandler von ResolveHandler . Wenn es um DLLs im gemischten Modus geht, habe ich viele der Varianten und Varianten von ResolveHandler , die für mich nicht funktionieren (alle, die dll-Bytes im Speicher lesen und daraus lesen). Sie alle arbeiteten für Managed Dlls. Hier ist, was bei mir funktioniert hat:

 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, die Bytes in eine Datei zu schreiben und von ihrem Ort zu laden. Um das Henne-und-Ei-Problem zu vermeiden, müssen Sie sicherstellen, dass Sie den Handler vor dem Zugriff auf die Assembly deklarieren und nicht auf die Assembly-Member (oder Instanzen, die mit der Assembly instanziieren müssen) innerhalb des Lade- (Assembly Resolving) Teils zugreifen. GetMyApplicationSpecificPath() sicher, dass GetMyApplicationSpecificPath() kein GetMyApplicationSpecificPath() Verzeichnis ist, da temporäre Dateien möglicherweise von anderen Programmen oder von Ihnen selbst gelöscht werden (nicht, dass es gelöscht wird, während Ihr Programm auf die DLL zugreift, aber es ist ein Ärgernis). AppData ist ein guter Standort). Beachten Sie auch, dass Sie die Bytes jedes Mal schreiben müssen, Sie können nicht von Ort laden, nur weil die DLL bereits dort residiert.

Wenn die Assembly vollständig nicht verwaltet wird, können Sie diesen oder diesen Link zum Laden solcher DLLs sehen.

PostBuild von Xenocode kann sowohl gemanagte als auch nicht gemanagte Dateien in eine einzige EXE- Datei packen.