ILMerge kann Assemblys zu einer einzigen Assembly kombinieren, sofern die Assembly nur Code verwaltet. Sie können die Befehlszeilen-App verwenden oder einen Verweis auf die Exe hinzufügen und programmgesteuert zusammenführen. Für eine GUI-Version gibt es Eazfuscator und auch .Netz, die beide kostenlos sind. Bezahlte Apps sind BoxedApp und SmartAssembly .
Wenn Sie Assemblys mit nicht verwaltetem Code zusammenführen müssen, würde ich SmartAssembly empfehlen . Ich hatte nie Probleme mit SmartAssembly, sondern mit allen anderen. Hier können die erforderlichen Abhängigkeiten als Ressourcen in Ihre Haupt-Exe eingebettet werden.
Sie können dies alles manuell tun, ohne sich Sorgen machen zu müssen, ob die Assembly verwaltet wird oder sich im gemischten Modus befindet, indem Sie die DLL in Ihre Ressourcen einbetten und sich dann auf die Assembly von AppDomain verlassen ResolveHandler
. Dies ist eine One-Stop-Lösung, bei der der schlimmste Fall übernommen wird, dh Assemblys 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 hier ist, die Bytes in eine Datei zu schreiben und von ihrem Speicherort zu laden. Um Henne-Ei-Probleme zu vermeiden, müssen Sie sicherstellen, dass Sie den Handler deklarieren, bevor Sie auf die Baugruppe zugreifen, und dass Sie nicht auf die Baugruppenelemente zugreifen (oder alles instanziieren, was mit der Baugruppe zu tun hat). Stellen Sie außerdem sicher, dass GetMyApplicationSpecificPath()
kein temporäres Verzeichnis vorhanden ist, da versucht werden könnte, temporäre Dateien von anderen Programmen oder von Ihnen selbst zu löschen (nicht, dass sie gelöscht werden, während Ihr Programm auf die DLL zugreift, aber zumindest ist dies ein Ärgernis. AppData ist gut Standort). Beachten Sie auch, dass Sie die Bytes jedes Mal schreiben müssen. Sie können nicht vom Speicherort laden, nur weil sich die DLL bereits dort befindet.
Für verwaltete DLLs müssen Sie keine Bytes schreiben, sondern direkt vom Speicherort der DLL laden oder einfach die Bytes lesen und die Assembly aus dem Speicher laden. So oder so:
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 Assembly vollständig unmanaged ist, können Sie diese sehen Link oder das , wie solche DLLs zu laden.