Как стать автором
Обновить

Создание динамически загружаемой DLL библиотеки на C#

Задача

Не так давно у нас появилась необходимость создать расширение для одной программы на языке C# с использованием WPF. Расширение представляет собой динамически загружаемую dll библиотеку, о создании которой и пойдет речь в данной статье.

Нам не удалось найти стандартное средство в языке C# для создание динамической dll, по этому были рассмотрены обходные методы:

Первый способ – это создание динамически загружаемой dll на managed C++, из которой, производилось обращение к сборке на C#

Второй способ – создание сборки на языке C# и путем декомпиляции в IL код и обратно, приведение этой библиотеки к нужному виду.

О втором способе расскажу подробнее:

Создание динамической dll путем пере компиляции в il

Для реализации нам потребуются две утилиты ilasm и ildasm, эти утилиты должны поставляться вместе со средой разработки, у меня они лежали в этих папках:

C:\Windows\Microsoft.NET\Framework\v4.0.30319\

C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin\NETFX 4.0 Tools

Для удобства я добавил эти пути в Path, потому что придется часто пользоваться этими утилитами в командной строке.

Далее необходимо создать библиотеку классов на языке C#. Функции которые необходимо экспортировать, должны быть публичными и статическими, и находиться в публичном классе. В качестве параметров и возвращаемого значения можно использовать простые типы, такие как string, int.

Пример кода:
public class TestExportClass
{
public static void Run()
{
MessageBox.Show("Привет из C#");
}
}


Скомпилируем проект, получаем dll библиотеку. (у меня TestDll.dll)

Теперь необходимо преобразовать dll библиотеку в il код. Для этого нужно запустить ildasm в командной строке со следующими параметрами

ildasm TestDll.dll /OUT:TestDll.il


Далее необходимо проделать некоторые манипуляции с получившимся il кодом.

Во-первых, меняем флаг

.corflags 0×00000001


на

.corflags 0×00000002


Во-вторых, над началом описания классов (обычно эта область отделена комментарием CLASS MEMBERS DECLARATION) добавляем код:

.vtfixup [1] int32 fromunmanaged at VT_01

.data VT_01 = int32(0)


В-третьих, в методе который необходимо сделать экспортируемым добавляем код:

.vtentry 1 : 1

.export [1] as Run


Здесь Run – это название метода, по которому его будет вызывать сборка, написанная на неуправляемом коде.

Теперь необходимо скомпилировать dll библиотку, для этого воспользуемся утилитой ilasm, с параметрами:

ilasm TestDll.il /OUT:TestDll.dll /DLL


Все после этого dll можно использовать как обычную динамически загружаемую dll библиотеку.

Динамическая dll + WPF


Если вы планируете создавать расширение с использованием технологий, требующих, чтобы приложение работало в STA потоке (Например WPF), то необходимо учесть, что поток в котором будет выполняться расширение наследуется от сборки запустившей библиотеку, а значит может быть не в режиме STA.

Для того чтобы обойти эту проблему было решено в расширении создать STA поток и в нем запускать окна на WPF.

Вот так можно модернизировать код для запуска WPF окна:

public static void Run()
{
Thread WPFThread = new Thread(OpenWTPWindow);
WPFThread.ApartmentState = ApartmentState.STA;
WPFThread.Start();
WPFThread.Join();
}

public static void OpenWTPWindow()
{
System.Windows.Window WPFWindow = new System.Windows.Window();
WPFWindow.ShowDialog();
}


Обратите внимание что окно запускается не с помощью функции Show() а ShowDialog(), функция Show() работает некорректно, при использовании её не в основном потоке.

Заключение


Такой метод зарекомендовал себя при разработки расширений для различных программ которые требуют, в качестве подключаемого модуля динамически загружаемую DLL библиотеку.

Справедливости ради стоит заметить, что после завершения вызванной процедуры, подгруженная dll библиотека продолжает находиться в памяти, что вызывает некоторые проблемы:
Например, когда мы создавали расширение для сервиса который постоянно запущен в системе, чтобы установить пользователю обновленное расширение, приходилось временно приостанавливать сервис.

Ссылки по теме


Хорошая статья. Если у вас остались еще какие то вопросы по созданию динамической dll, рекомендую обратиться к ней.
Теги:
Хабы:
Данная статья не подлежит комментированию, поскольку её автор ещё не является полноправным участником сообщества. Вы сможете связаться с автором только после того, как он получит приглашение от кого-либо из участников сообщества. До этого момента его username будет скрыт псевдонимом.