ILMerge может объединять сборки в одну сборку, если сборка содержит только управляемый код. Вы можете использовать приложение командной строки, или добавить ссылку на исполняемый файл и программно объединить. Для версии с графическим интерфейсом есть Eazfuscator , а также .Netz, которые бесплатны. Платные приложения включают BoxedApp и SmartAssembly .
Если вам нужно объединить сборки с неуправляемым кодом, я бы предложил SmartAssembly . У меня никогда не было икоты с SmartAssembly, но со всеми остальными. Здесь он может встраивать необходимые зависимости как ресурсы в ваш основной исполняемый файл.
Вы можете делать все это вручную, не беспокоясь о том, что сборка управляется или в смешанном режиме, встраивая dll в ваши ресурсы, а затем полагаясь на сборку AppDomain ResolveHandler
. Это универсальное решение, принявшее наихудший вариант, то есть сборки с неуправляемым кодом.
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);
};
}
Ключевым моментом здесь является запись байтов в файл и загрузка из него. Чтобы избежать проблемы с курицей и яйцом, необходимо убедиться, что вы объявили обработчик перед доступом к сборке, и чтобы у вас не было доступа к элементам сборки (или к созданию экземпляров всего, что имеет отношение к сборке) внутри загрузочной (разрешающей сборку) детали. Также позаботьтесь о том, чтобы GetMyApplicationSpecificPath()
не было никакого временного каталога, поскольку временные файлы можно было пытаться стереть другими программами или самостоятельно (не то, что он будет удален, когда ваша программа обращается к dll, но, по крайней мере, это неприятно. AppData хорош расположение). Также обратите внимание, что вы должны записывать байты каждый раз, вы не можете загрузить из местоположения только потому, что dll уже находится там.
Для управляемых dll вам не нужно записывать байты, а непосредственно загружать из местоположения dll или просто читать байты и загружать сборку из памяти. Как это или так:
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.
Если сборка полностью неуправляемая, вы можете увидеть эту ссылку или это о том, как загрузить такие библиотеки.