Я пытаюсь выгрузить неверную версию сторонней DLL из моего .NET-процесса, поскольку она, похоже, вызывает проблему, которая всегда разрешается перезагрузкой моего приложения. Вместо перезапуска приложения я бы хотел удалить и перезагрузить DLL.
DLL загружается с помощью LoadLibrary
и удаляется с помощью FreeLibrary
(используя DllImport
, взятый с веб-сайта P/Invoke).
Когда я вызываю 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/С++
- К сожалению, мой процесс ограничивается только использованием .NET 2 (поэтому нет решения WCF).
- Я использую WinXP Pro x64 SP2, но решение должно быть совместимо с XP, Win7 x32/x64 и т.д.
- DLL используется для связи с токеном USB