ILMerge может объединять сборки в одну сборку, если сборка содержит только управляемый код. Вы можете использовать приложение командной строки или добавить ссылку на исполняемый файл и программно объединить. Для версии с графическим интерфейсом есть Eazfuscator , а также .Netz , которые бесплатны. Платные приложения включают BoxedApp и SmartAssembly .
Если вам нужно объединить сборки с неуправляемым кодом, я бы предложил SmartAssembly . У меня никогда не было икоты с SmartAssembly , но со всеми остальными. Здесь он может встраивать необходимые зависимости как ресурсы в ваш основной exe-файл.
Вы можете делать все это вручную, не беспокоясь о том, что сборка управляется или в смешанном режиме, встраивая 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.
Если сборка полностью неуправляемая, вы можете увидеть эту ссылку или эту о том, как загрузить такие библиотеки.