Как скомпилировать все проекты солюшена в один .EXE?

180
05 февраля 2018, 02:35

Есть солюшен (Solution). В нем 4 проекта. Один главный, три второстепенных. Главный проект использует типы из второстепенных и наоборот. Короче все они переплетены. Как все это скомпилировать в один .EXE файл для последующего распространения?

UPD Т.к. похоже,что не все поняли о чем речь, то постараюсь дополнить свой вопрос.

Вот небольшой пример: В solution Explorer видно, что в Solution добавлено два проект. Проект App2 зависит от проекта App1. App1 добавлен в References.

Так же прописаны соответствующие зависимости.

Если просто откомпилировать этот Solution, то на выходе получим два файла - App2.exe и App1.dll. Таким образом, чтобы приложение заработало, скажем на другом компьютере, нужно переписать туда два этих файла. Иначе произойдет ошибка времени выполнения. Что-то вроде Could not load file or assembly. The system cannot find the file specified. Так вот хотелось бы откомпилировать приложение таким образом, чтобы в итоге получился только один файл - App2.exe. И чтобы распространять это приложение можно было одним файлом. А файл App1.dll была как бы встроена в него.

Answer 1

Возможные решения:

Слияние сборок в одну после компиляции

Несколько сборок можно склеить в одну уже после компиляции, используя утилиту ILMerge.

Она есть на NuGet.org:

Install-Package ilmerge

Формат вызова:

ilmerge
  /lib:"C:\Windows\Microsoft.NET\Framework64\v4.0.30319"
  /lib:"C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\PublicAssemblies"
  /targetplatform:v4
  /out:out.dll mydll1.dll mydll2.dll

перед использованием пути стоит подправить на актуальные.

Аналогичные утилиты - il-repack, Mono.Merge

Включение DLL в EXE в виде Embedded Resource с подменой стандартного механизма загрузки:
  1. Добавить bin\someassembly.dll в проект exe через Add Existing Item / стрелка на Add / Add as Link, выставить Build Type = Embedded Resource
  2. Добавить проект someassembly в References. Выставить у референса Copy Local = false - чтобы избежать копирования в bin.
  3. Обработать CurrentDomain_AssemblyResolve:

    using System;
    using System.Reflection;
    using System.Windows.Forms;
    namespace WindowsFormsApplication7
    {
        static class Program
        {
            [STAThread]
            static void Main()
            {
                AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new Form1());
            }
            private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
            {
                var assemblyName = new AssemblyName(args.Name).Name;
                if (assemblyName == "someassembly")
                {
                    using (var stream = typeof(Program).Assembly.GetManifestResourceStream(
                        "WindowsFormsApplication7." + assemblyName + ".dll"))
                    {
                        byte[] assemblyData = new byte[stream.Length];
                        stream.Read(assemblyData, 0, assemblyData.Length);
                        return Assembly.Load(assemblyData);
                    }
                }
                else
                {
                    return null;
                }
            }
        }
    }
    

Это минимальный рабочий пример. Если не работает - запускайте под отладчиком. Скорее всего вы не угадали с именем ресурса, и GetManifestResourceStream возвращает null. Убедитесь, что тип у айтема выставлен именно в Embedded Resource (а не просто в Resource). Просмотреть имена всех доступных ресурсов можно прямо в отладчике, вызовом

typeof(Program).Assembly.GetManifestResourceNames()

Проект целиком на гитхабе, на примере SevenZipSharp: https://github.com/PashaPash/SevenZipSharp-Embedded

Включение сборок в виде ресурсов, автоматический вариант

Устанавливаете пакет Costura.Fody через nuget и получаете один exe на выходе.

> PM> Install-Package Costura.Fody
Альтернативы:
  • Решение от Vlad - компиляция в netmodule с последющим слиянием
  • Сборка через добавление всех исходников в еще один большой проект - от @Qwertiy
Answer 2

Поправлю сам себя, решить проблему Вам поможет маленькая утилита от Microsoft - ILMerge. Добавлю, что есть хорошая статья на данную тему

Answer 3

Есть ещё и костыльный способ: создать новый проект и в него добавить как существующие все файлы с кодом, после чего скомпилировать.

Answer 4

Вообще, когда вы билдите Solution, то в папке bin каждого из 3-х проектов в итоге будет dll, в основном проекте .exe

Вы можете в главном проекте Project Properties -> Resources -> Add Resource -> Add Existing File добавить ссылки на все эти dll. В итоге будет .exe у главного проекта, который все остальные в себе включает.

READ ALSO
C# TCP Отправить hex

C# TCP Отправить hex

Как отправить в C# hex а не string на tcp? Использую для проверки програму-клиент-сервер и если конвертировать string в байты то эта программа получит...

168
Выделение ячейки DataGridView

Выделение ячейки DataGridView

Написал вот такой код:

195
TypeError: textureLoader.addEventListener is not a function

TypeError: textureLoader.addEventListener is not a function

В консоли выводится TypeError: textureLoaderaddEventListener is not a function

287