Форум программистов, компьютерный форум, киберфорум
C# .NET
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.84/25: Рейтинг темы: голосов - 25, средняя оценка - 4.84
 Аватар для prog63
2 / 2 / 1
Регистрация: 24.11.2013
Сообщений: 77

Склеивание .dll и пользовательского .exe

09.04.2016, 14:31. Показов 4759. Ответов 8

Студворк — интернет-сервис помощи студентам
Доброго времени суток, уважаемые форумчане !
Вложений всего пять, поэтому выкладываю все одним большим архивом : TEST.rar Зеркало
Поставлена такая задача :

Есть у меня библиотека Lib с таким кодом :
Кликните здесь для просмотра всего текста
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace Lib
{
    public class LibClass
    {
        public delegate void OnKeyPressingContainer(ConsoleKeyInfo Key);
        public static event OnKeyPressingContainer OnKeyPressing;
        public delegate void OnKeyPressedContainer(ConsoleKeyInfo Key);
        public static event OnKeyPressedContainer OnKeyPressed;
        private static void KeyPress(ConsoleKeyInfo Key)
        {
            if (OnKeyPressing != null) OnKeyPressing(Key);
            Console.WriteLine("Key : " + Key.Key + " (\'" + Key.KeyChar + "\')");
            if (OnKeyPressed != null) OnKeyPressed(Key);
        }
        public static void Process()
        {
            ConsoleKeyInfo Key = new ConsoleKeyInfo();
            while (Key.Key != ConsoleKey.Escape)
            {
                Key = Console.ReadKey(true);
                KeyPress(Key);
                Console.WriteLine();
            }
        }
    }
}

Как видно, она в функции Process ожидает нажатия клавиши, затем вызывает событие OnKeyPressing, обрабатывает нажатие и вызывает событие OnKeyPressed.
Весь ее проект - Lib.rar во вложении.

Есть так же приложение Main с таким кодом :
Кликните здесь для просмотра всего текста
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;
using Lib;
 
namespace Main
{
 
    class Program
    {
        static void Main(string[] args)
        {
            LibClass.OnKeyPressing += KeyPressing;
            LibClass.OnKeyPressed += KeyPressed;
            LibClass.Process();
        }
        static void KeyPressing(ConsoleKeyInfo Key) { Console.WriteLine("KeyPressing : \'" + Key.KeyChar + "\'"); }
        static void KeyPressed(ConsoleKeyInfo Key) { Console.WriteLine("KeyPressed : \'" + Key.KeyChar + "\'"); }
    }
}

Как видно, оно подписывается на события библиотеки и вызывает из нее функцию Process.
Весь его проект - Main.rar во вложении.

Все работает замечательно. Но !
Необходимо иметь на выходе только Main.exe, т.е. склеить его с библиотекой.
________________________________________ ________________________________________ __________________
И тут начались попытки.
Пробовал ILMerge :
Начал, вооружившись этой статьей на Хабре.
Пользовался тем, что есть во вложении.
1. Создал папку TEST.
2. Положил туда ILMerge.exe, Lib.dll и Main.exe.
3. Создал там Merge.bat следующего содержания :
Code
1
ILMerge.exe /target:Exe /out:Compressed.exe Main.exe /log:Log.txt Lib.dll
4. Запустил его.
5. ILMerge создал Compressed.exe и Compressed.pdb, и вывел в Log.txt следующее :
Кликните здесь для просмотра всего текста
ILMerge version 2.12.803.0
Copyright (C) Microsoft Corporation 2004-2006. All rights reserved.
ILMerge /target:Exe /out:Compressed.exe Main.exe /log:Log.txt Lib.dll
Set platform to 'v2', using directory 'C:\Windows\Microsoft.NET\Framework64\v2 .0.50727\..\v2.0.50727' for mscorlib.dll
Running on Microsoft (R) .NET Framework v2.0.50727
mscorlib.dll version = 2.0.0.0
The list of input assemblies is:
Main.exe
Lib.dll
Trying to read assembly from the file 'D:\Tempo\TEST\Main.exe'.
Can not find PDB file. Debug info will not be available for assembly 'Main.exe'.
Successfully read in assembly.
There were no errors reported in Main's metadata.
Trying to read assembly from the file 'D:\Tempo\TEST\Lib.dll'.
Can not find PDB file. Debug info will not be available for assembly 'Lib.dll'.
Successfully read in assembly.
There were no errors reported in Lib's metadata.
Checking to see that all of the input assemblies have a compatible PeKind.
Main.PeKind = ILonly, Requires32bits, Prefers32bits
Lib.PeKind = ILonly
All input assemblies have a compatible PeKind value.
AssemblyResolver: Assembly 'Main' is referencing assembly 'System'.
AssemblyResolver: Attempting referencing assembly's directory.
AssemblyResolver: Did not find assembly in referencing assembly's directory.
AssemblyResolver: Attempting input directory.
AssemblyResolver: Did not find assembly in input directory.
AssemblyResolver: Attempting user-supplied directories.
AssemblyResolver: No user-supplied directories.
AssemblyResolver: Attempting framework directory.
Can not find PDB file. Debug info will not be available for assembly 'System'.
Resolved assembly reference 'System' to 'C:\Windows\Microsoft.NET\Framework64\v2 .0.50727\..\v2.0.50727\System.dll'. (Used framework directory.)
Using assembly 'Main' for assembly-level attributes for the target assembly.
Merging assembly 'Main' into target assembly.
Merging assembly 'Lib' into target assembly.
Copying 2 Win32 Resources from assembly 'Main' into target assembly.
Transferring entry point 'Main.Program.Main(System.String[])' from assembly 'Main' to assembly 'Compressed'.
There were no errors reported in the target assembly's metadata.
ILMerge: Writing target assembly 'Compressed.exe'.
Location for referenced assembly 'mscorlib' is 'C:\Windows\Microsoft.NET\Framework64\v2 .0.50727\mscorlib.dll'
There were no errors reported in mscorlib's metadata.
Location for referenced assembly 'System' is 'C:\Windows\Microsoft.NET\Framework64\v2 .0.50727\system.dll'
There were no errors reported in System's metadata.
ILMerge: Done.

Судя по надписям "There were no errors reported in" и "Done", ILMerge полагает, что все нормально.
Но Compressed.exe при запуске вылетает с APPCRASH (ILMergeCrash.jpg во вложении).
Все остальные биения и мучения ни к чему не привели.
Итак, с ILMerge покончено.
________________________________________ ________________________________________ __________________
Дальнейшие попытки привели меня к такому решению : положить библиотеку во встраиваемые ресурсы.
Нарыл немного ссылок :
Как объединить exe и Dll в один файл
Подключение dll из ресурсов
https://geektimes.ru/post/67836/
https://msdn.microsoft.com/ru-... s.90).aspx
https://msdn.microsoft.com/ru-... s.90).aspx
И, наконец, http://www.codeproject.com/Art... d-Resource.
Там есть пример, но если кто-то не зарегистрирован на codeproject и не хочет, то архив есть во вложении.
1. Как там написано, добавляю Lib.dll как файл в проект.
2. Для библиотеки, которая в References, устанавливаю параметр "Копировать локально" в "False", а для той, которая файл - "Действие при сборке" во "Внедренный ресурс".
3. Добавляю в проект EmbeddedAssembly.cs.
4. Добавляю в код Main using System.Reflection;
5. Изменяю код Main следующим образом :
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
[STAThread]
        static void Main(string[] args)
        {
            EmbeddedAssembly.Load("Main.Lib.dll", "Lib.dll");
            AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
            LibClass.OnKeyPressing += KeyPressing;
            LibClass.OnKeyPressed += KeyPressed;
            LibClass.Process();
        }
        static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
        {
            return EmbeddedAssembly.Get(args.Name);
        }
Собираю, запускаю. Получаю FileNotFoundException, говорящий про Lib.dll.
По идее, если сборка не найдена, должна вызваться CurrentDomain_AssemblyResolve.
Она, в свою очередь, должна загрузить из ресурсов библиотеку и передать её кому нужно.
Она этого не делает, потому что если библиотеке в References вернуть параметр "Копировать локально" в "True", то всё будет работать, как раньше.
________________________________________ ________________________________________ __________________
Что я делаю не так и есть ли альтернативы ?

Заранее благодарен за помощь.
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
09.04.2016, 14:31
Ответы с готовыми решениями:

Склеивание *.exe файлов
Как склеить два экзешника? Тупа склеить я и сам могу. Мне надо, что-бы они оба работали. Не подумайте ни чего плохого. Так...Для общего...

Склеивание .dll и пользовательского .exe
Склеиваю MaterialSkin.dll и свой exe при помощи ILMerge батник вида /t:winexe /out:test.exe Finish.exe MaterialSkin.dll Содается...

Склеивание двух exe
Подскажите прогу для склеивангимя 2-х *.ехе

8
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
09.04.2016, 16:26
Цитата Сообщение от prog63 Посмотреть сообщение
есть ли альтернативы ?
Если не пугает использование типа dynamic и отсутствие строгой типизации - то вот так, самое простое.
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Reflection;
using System.IO;
 
namespace WindowsFormsApplication1 {
    public partial class MainForm : Form {
        public MainForm() {
            InitializeComponent();
            button1.Click += new EventHandler(button1_Click);
        }
 
        void button1_Click(object sender, EventArgs e) {
            Assembly asm = Assembly.Load(Resource1.testlib);
            Type t = asm.GetType("testlib.TestClass");
            dynamic test = Activator.CreateInstance(t);
            MessageBox.Show(test.GetResult(), "test");
        }
    }
}
Сборка лежит в ресурсах, просто через рефлексию ее берем и создаем наш тип.
1
Эксперт .NET
 Аватар для Rius
13161 / 7720 / 1679
Регистрация: 25.05.2015
Сообщений: 23,517
Записей в блоге: 14
09.04.2016, 16:52
Цитата Сообщение от prog63 Посмотреть сообщение
Необходимо иметь на выходе только Main.exe, т.е. склеить его с библиотекой.
Почему код не встроить в один проект?
Почему не dll + exe? Чем вызвана необходимость?
0
 Аватар для prog63
2 / 2 / 1
Регистрация: 24.11.2013
Сообщений: 77
09.04.2016, 20:11  [ТС]
Цитата Сообщение от Rius Посмотреть сообщение
Почему код не встроить в один проект?
Это не подходит. Простите, я забыл об этом упомянуть.
0
Эксперт .NET
 Аватар для Rius
13161 / 7720 / 1679
Регистрация: 25.05.2015
Сообщений: 23,517
Записей в блоге: 14
09.04.2016, 21:29
Объясните, почему? Зачем делать dll, если нельзя поставлять dll отдельно? И почему нельзя встроить код библиотеки в проект, если нужно чтобы это был один файл?
0
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
09.04.2016, 21:31
Цитата Сообщение от Rius Посмотреть сообщение
Зачем делать dll, если нельзя поставлять dll отдельно? И почему нельзя встроить код библиотеки в проект, если нужно чтобы это был один файл?
Rius, мы не ищем легких путей. Копаем отсюда и до обеда.
0
 Аватар для Mikant
1322 / 995 / 127
Регистрация: 08.12.2009
Сообщений: 1,299
10.04.2016, 00:08
prog63, в дополнение к ответу insite2012, я бы предложил хранить библиотеку в ресурсах, но не в ущерб компиляции. Пример использования в приложенном проекте. В этом решении два проекта: ConsoleApplication1 и ClassLibrary1. При запуске ConsoleApplication1.exe обращается к ClassLibrary1.dll, но ему абсолютно не важно, есть ли рядом эта сборка: при отсутствии, он сам загрузит её в память из ресурсов. Для демонстрации, после компиляции можно просто удалить файл библиотеки и запустить exe.

На что стоит обратить особое внимание при чтении кода:
1) Подписка на AssemblyResolve происходит выше по стеку, чем первое упоминание Class1
2) На то, как устроен квалификатор пути при вызове GetManifestResourceStream и какой тип использован для выбора сборки
3) Сборка библиотеки добавлена как ссылка (важно, если код библиотеки обновляется)
Вложения
Тип файла: 7z ConsoleApplication1.7z (2.0 Кб, 16 просмотров)
3
 Аватар для prog63
2 / 2 / 1
Регистрация: 24.11.2013
Сообщений: 77
13.04.2016, 19:14  [ТС]
Спасибо ! Попробую разобраться с Вашим решением.
0
Почетный модератор
Эксперт С++
 Аватар для SatanaXIII
5851 / 2862 / 392
Регистрация: 01.11.2011
Сообщений: 6,906
20.01.2017, 13:10
Цитата Сообщение от Rius Посмотреть сообщение
Объясните, почему? Зачем делать dll, если нельзя поставлять dll отдельно? И почему нельзя встроить код библиотеки в проект, если нужно чтобы это был один файл?
Например, если библиотека чужая.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
20.01.2017, 13:10
Помогаю со студенческими работами здесь

Svchost.exe, onion.exe, openvg.exe torrc и куча dll и cl, а также папка tor в Roaming

Как множество dll собрать в один dll или exe файл?
Сделал тестовый проектик по работе с БД (Entity Framework), скомпилировал и как глянул в папку Debug....., а там куча dll файлов. Путем...

Куда компилятор csc.exe кладёт скомпилированные .exe/.dll?
Куда компилятор csc.exe кладёт скомпилированные .exe/.dll? Есть батник, компиляция проекта в Visual Studio происходит успешно, никаких...

Возможно ли собрать .exe и несколько .dll в один .exe?
Просто написал программку, получилось >6 .dll файлов, с этим ничего нельзя поделать без "отучения Qt"?

AppModule.exe - точка входа в процедуру cuLaunchKernel_ptsz не найдена в библиотеке DLL nvcuda.dll
Добрый день, После серии неудачных экспериментов с установкой и попыткой починить программы имею вот такую ошибку. AppModule.exe...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
9
Ответ Создать тему
Новые блоги и статьи
Как я обхитрил таблицу Word
Alexander-7 21.03.2026
Когда мигает курсор у внешнего края таблицы, и нам надо перейти на новую строку, а при нажатии Enter создается новый ряд таблицы с ячейками, то мы вместо нервных нажатий Энтеров мы пишем любые буквы. . .
Krabik - рыболовный бот для WoW 3.3.5a
AmbA 21.03.2026
без регистрации и смс. Это не торговля, приложение не содержит рекламы. Выполняет свою непосредственную задачу - автоматизацию рыбалки в WoW - и ничего более. Однако если админы будут против -. . .
Программный отбор значений справочника
Maks 21.03.2026
Установка программного отбора значений справочника "Сотрудники" из модуля формы документа. В качестве фильтра для отбора служит предопределенное значение перечислений. Процедура. . .
Переходник USB-CAN-GPIO
Eddy_Em 20.03.2026
Достаточно давно на работе возникла необходимость в переходнике CAN-USB с гальваноразвязкой, оный и был разработан. Однако, все меня терзала совесть, что аж 48-ногий МК используется так тупо: просто. . .
Оттенки серого
Argus19 18.03.2026
Оттенки серого Нашёл в интернете 3 прекрасных модуля: Модуль класса открытия диалога открытия/ сохранения файла на Win32 API; Модуль класса быстрого перекодирования цветного изображения в оттенки. . .
SDL3 для Desktop (MinGW): Рисуем цветные прямоугольники с помощью рисовальщика SDL3 на Си и C++
8Observer8 17.03.2026
Содержание блога Финальные проекты на Си и на C++: finish-rectangles-sdl3-c. zip finish-rectangles-sdl3-cpp. zip
Символические и жёсткие ссылки в Linux.
algri14 15.03.2026
Существует два типа ссылок — символические и жёсткие. Ссылка в Linux — это запись в каталоге, которая может указывать либо на inode «файла-ИСТОЧНИКА», тогда это будет «жёсткая ссылка» (hard link),. . .
[Owen Logic] Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора
ФедосеевПавел 14.03.2026
Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора ВВЕДЕНИЕ Выполняя задание на управление насосной группой заполнения резервуара,. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru