ILMerge kann Baugruppen zu einer einzigen Baugruppe kombinieren, sofern die Baugruppe nur verwalteten Code enthält. Sie können die Befehlszeilenanwendung verwenden oder einen Verweis auf die Exe hinzufügen und programmatisch zusammenführen. Für eine GUI-Version gibt es Eazfuscator und auch .netz die beide kostenlos sind. Kostenpflichtige Apps umfassen BoxedApp et SmartAssembly .
Wenn Sie Assemblies mit nicht verwaltetem Code zusammenführen müssen, würde ich vorschlagen SmartAssembly . Ich hatte nie Schluckauf mit SmartAssembly sondern mit allen anderen. Hier kann es die erforderlichen Abhängigkeiten als Ressourcen in Ihre Haupt-Exe einbetten.
Sie können all dies manuell tun, ohne sich darum kümmern zu müssen, ob die Assembly verwaltet oder im gemischten Modus ist, indem Sie die DLL in Ihre Ressourcen einbetten und sich dann auf die Assembly von AppDomain verlassen ResolveHandler
. Dies ist eine Lösung aus einem Guss, indem der schlimmste Fall angenommen wird, d.h. Baugruppen mit nicht verwaltetem Code.
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 dazu ist, die Bytes in eine Datei zu schreiben und von dort zu laden. Um das Henne-Ei-Problem zu vermeiden, müssen Sie sicherstellen, dass Sie den Handler deklarieren, bevor Sie auf die Assembly zugreifen, und dass Sie nicht auf die Assembly-Mitglieder zugreifen (oder irgendetwas instanziieren, das mit der Assembly zu tun hat) innerhalb des Ladeteils (Assembly-Auflösung). Achten Sie auch darauf, dass GetMyApplicationSpecificPath()
ist kein temporäres Verzeichnis, da temporäre Dateien von anderen Programmen oder von Ihnen selbst gelöscht werden könnten (nicht, dass sie gelöscht werden, während Ihr Programm auf die dll zugreift, aber es ist zumindest ein Ärgernis). AppData ist ein guter Ort). Beachten Sie auch, dass Sie die Bytes jedes Mal neu schreiben müssen, Sie können nicht von einem Ort laden, nur weil die Dll dort bereits vorhanden ist.
Bei verwalteten DLLs müssen Sie keine Bytes schreiben, sondern direkt vom Speicherort der DLL laden oder nur die Bytes lesen und die Assembly aus dem Speicher laden. So oder so ähnlich:
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.
Wenn die Baugruppe vollständig unverwaltet ist, können Sie Folgendes sehen Link o ce wie man solche DLLs lädt.