Я пытаюсь выгрузить некорректно работающую стороннюю DLL из моего процесса .NET, так как это, кажется, вызывает проблему, которая всегда решается путем перезапуска моего приложения.Вместо того, чтобы перезапускать приложение, я хотел бы вместо этого удалить и перезагрузить DLL.
DLL загружается с помощью LoadLibrary
и удаляется с помощью FreeLibrary
(с использованием DllImport
s, взятых из P /Запустить сайт).Когда я вызываю LoadLibrary()
, я вижу, что DLL появляется в списке DLL в Process Explorer, и когда я звоню FreeLibrary()
, я вижу, что DLL исчезает из списка DLL - как и ожидалось.
Однако однаждыЯ вызвал функцию Initialize()
сторонней библиотеки, FreeLibrary()
больше не удаляет DLL из списка, даже если я предварительно вызываю соответствующий метод Deinit()
.Вызов другой функции в библиотеке не имеет этой проблемы.Однако перед использованием я должен Initialise()
библиотеку!
Я попытался изолировать библиотеку DLL, создав ее в своем собственном AppDomain
, а затем выгрузить этот домен после освобождения библиотеки DLL.
Я не получаю кодов ошибок или исключений от Initialize()
или Deinit()
, от LoadLibrary()
или FreeLibrary()
или от создания или выгрузки AppDomain
.
. Я использовал следующий код для созданияAppDomain
и инициализация:
string pathToDll = Assembly.GetExecutingAssembly().CodeBase;
m_Domain = AppDomain.CreateDomain("MyAppDomain", null, new AppDomainSetup { PrivateBinPath = pathToDll });
m_Module = (ThirdPartyModule)m_Domain.CreateInstanceFromAndUnwrap(pathToDll, typeof(ThirdPartyModule).FullName);
m_Module.Init();
Для деинициализации и выгрузки AppDomain
:
m_Module.Free();
m_Module = null;
if (m_Domain != null)
{
AppDomain.Unload(m_Domain);
m_Domain = null;
}
Наконец, мой класс сборки ThirdPartyModule:
internal class ThirdPartyModule : MarshalByRefObject
{
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
internal static extern IntPtr LoadLibrary(string lpFileName);
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool FreeLibrary(IntPtr hModule);
public IntPtr Module { get; set; }
public ThirdPartyModule()
{
Module = LoadLibrary("Misbehaving.dll");
}
public void Free()
{
FreeLibrary(Module);
Module = IntPtr.Zero;
}
// ...
}
это должно выглядеть так, как я ожидал?Если нет, есть ли какой-нибудь другой способ убедиться, что эта DLL полностью выгружена моим процессом?
Редактировать: Больше информации
- DLL содержит нативнуюкод, вероятно скомпилированный из C / C ++
- К сожалению, мой процесс ограничен использованием только .NET 2 (поэтому нет решения WCF).
- Я использую WinXP Pro x64 SP2, но решение должно бытьСовместимость с XP, Win7 x32 / x64 и т. Д.
- DLL используется для связи с USB-токеном