Ich habe ein Windows-C#-Programm, das eine C++-DLL für Daten-E/A verwendet. Mein Ziel ist es, die Anwendung als eine einzige EXE bereitzustellen.
Was sind die Schritte zur Erstellung einer solchen ausführbaren Datei?
Ich habe ein Windows-C#-Programm, das eine C++-DLL für Daten-E/A verwendet. Mein Ziel ist es, die Anwendung als eine einzige EXE bereitzustellen.
Was sind die Schritte zur Erstellung einer solchen ausführbaren Datei?
Bereitstellung von verwaltetem und nicht verwaltetem Code in einer einzigen Baugruppe Sonntag, Februar 4, 2007
.NET-Entwickler lieben die XCOPY-Bereitstellung. Und sie lieben einzelne Assembly-Komponenten. Zumindest fühle ich mich immer etwas unwohl, wenn ich eine Komponente verwenden muss und mir eine Liste von Dateien merken muss, die ich in die Haupt-Assembly dieser Komponente einfügen muss. Als ich also vor kurzem eine Komponente mit verwaltetem Code entwickeln musste und diese mit nicht verwaltetem Code aus einer C-DLL ergänzen musste (vielen Dank an Marcus Heege, der mir dabei geholfen hat!), habe ich mir überlegt, wie ich das Deployment der beiden DLLs vereinfachen kann. Wenn es sich nur um zwei Assemblies handeln würde, hätte ich ILmerge verwenden können, um sie in eine einzige Datei zu packen. Aber das funktioniert nicht bei gemischten Code-Komponenten mit sowohl verwalteten als auch nicht verwalteten DLLs.
Also habe ich mir folgende Lösung ausgedacht:
Ich schließe alle DLLs, die ich einsetzen möchte, als eingebettete Ressourcen in die Hauptbaugruppe meiner Komponente ein. Dann richte ich einen Klassenkonstruktor ein, um diese DLLs wie unten beschrieben zu extrahieren. Die Klasse ctor wird nur einmal innerhalb jeder AppDomain aufgerufen, so dass es ein vernachlässigbarer Overhead ist, 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 eingebunden, eine als nicht verwaltete DLL und eine als verwaltete DLL (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);
}
}
}
Die Arbeit mit einer verwalteten Code-Assembly wie dieser ist die gleiche wie immer - fast. Sie referenzieren sie (hier: ManagedService.dll) im Hauptprojekt Ihrer Komponente (hier: MyLib), setzen aber die Eigenschaft Copy Local auf false. Außerdem binden Sie die Assembly als Existing Item ein und setzen die Build Action auf Embedded Resource.
Für den nicht verwalteten Code (hier: UnmanagedService.dll) binden Sie die DLL einfach als Existing Item ein und setzen die Build Action auf Embedded Resource. Um auf die Funktionen zuzugreifen, verwenden Sie wie üblich das DllImport-Attribut, z. B.
[DllImport("unmanagedservice.dll")] public extern static int Add(int a, int b);
Das war's! Sobald Sie die erste Instanz der Klasse mit dem statischen ctor erstellen, werden die eingebetteten DLLs in eigene Dateien extrahiert und können verwendet werden, als ob Sie sie als separate Dateien bereitgestellt hätten. Solange Sie Schreibrechte für das Ausführungsverzeichnis haben, sollte das für Sie problemlos funktionieren. Zumindest für prototypischen Code halte ich diese Art der Bereitstellung einer einzelnen Assembly für recht praktisch.
Viel Spaß!
Essayer boxedapp ; es erlaubt, alle DLLs aus dem Speicher zu laden. Außerdem scheint es, dass Sie sogar .net runtime einbetten können. Gut, um eine wirklich eigenständige Anwendung zu erstellen...
Verwenden Sie Fody.Costura nuget
Das war's!
S http://www.manuelmeyer.net/2016/01/net-power-tip-10-merging-assemblies/
Haben Sie ILMerge ausprobiert? http://research.microsoft.com/~mbarnett/ILMerge.aspx
ILMerge ist ein Dienstprogramm, mit dem mehrere .NET-Assemblies zu einer einzigen Assembly zusammengeführt werden können. Es ist auf der Seite Tools & Utilities im Microsoft .NET Framework Developer Center frei verfügbar.
Wenn Sie die C++-DLL mit der Option /clr
Flag (ganz oder teilweise C++/CLI), dann sollte es funktionieren:
ilmerge /out:Composite.exe MyMainApp.exe Utility.dll
Mit einer gewöhnlichen (nativen) Windows-DLL wird es jedoch nicht funktionieren.
Klicken Sie einfach mit der rechten Maustaste auf Ihr Projekt in Visual Studio und wählen Sie Projekteigenschaften -> Ressourcen -> Ressource hinzufügen -> Vorhandene Datei hinzufügen Und fügen Sie den unten stehenden Code in Ihre App.xaml.cs oder eine ähnliche Datei 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 Blogbeitrag: http://codeblog.larsholm.net/2011/06/embed-dlls-easily-in-a-net-assembly/
CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.