Удалить C / clr dll с диска после FreeLibrary

#c #dll #clr

#c #dll #clr

Вопрос:

У меня есть очень простые exe и dll только для тестирования. Вот код в процессе exe:

 auto lib = ::LoadLibrary("CppDll.dll");
auto bar = (Bar)::GetProcAddress(lib, "Bar");
bar();
while (::FreeLibrary(lib));
 

Когда после этого я пытаюсь удалить DLL-файл, я вижу следующее:

введите описание изображения здесь

Я также заглянул в модули и я озадачен

 auto lib = ::LoadLibrary("CppDll.dll");
auto bar = (Bar)::GetProcAddress(lib, "Bar");
 

введите описание изображения здесь

 bar();
 

введите описание изображения здесь

 while (::FreeLibrary(lib));
 

введите описание изображения здесь

Итак, после вызова bar() их два. И FreeLibrary все-таки один остался.

Что я могу сделать, чтобы удалить файл?

UPD: Я только что обнаружил, что это происходит только в том случае, если dll поддерживает clr.

Ответ №1:

Это кажется невозможным. Приложение, в котором размещается среда CLR, использует CLRCreateInstance , из которого оно может получить ICLRMetaHost интерфейс, по которому оно может вызывать GetRuntime для создания среды CLR. Но в интерфейсе нет членов для выгрузки CLR. Его Stop метод останавливает выполнение кода в CLR, но не освобождает, не выделяет ресурсы и не выгружает домены приложений. Но чтобы выгрузить сборку, мы должны выгрузить все домены приложений, которые ее используют.

Итак, чтобы иметь возможность выгружать сборку, нужно загрузить ее в отдельный домен приложения, а затем выгрузить домен приложения. Но невозможно выгрузить DLL, которая загружает CLR, CLR может быть выгружена только при завершении процесса.

Richter, CLR через C #. Глава 22 «Хостинг CLR и домены приложений»:

Первый домен приложения, созданный при инициализации среды CLR, называется доменом приложения по умолчанию; этот домен приложения уничтожается только при завершении процесса Windows.