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