FreeLibrary无限期地返回true

时间:2018-02-05 21:12:51

标签: c# pinvoke dllimport loadlibrary python.net

为什么FreeLibrary会重复返回true?

我正在尝试从我的进程中卸载一些本机dll,所以我得到它的句柄,然后调用FreeLibrary,直到引用计数变为零,因此FreeLibrary返回false ...但它永远不会:

IntPtr pDll = DllLoadingImports.LoadLibrary(dllTounLoad);
//throw if pDll == IntPtr.Zero
while(DllLoadingImports.FreeLibrary(pDll));

代码运行,永不返回。 进程资源管理器也会显示仍然加载的dll。

更多背景资料:

我正在尝试卸载使用DllImport加载的本机库,我正在使用此处描述的技巧:https://stackoverflow.com/a/2445558/2308106 这是为了原型设计,所以我不必关心可能的结果......但我很困惑为什么图书馆不会卸载

修改1 : 我发现通过在GetModuleHandleEx函数中指定GET_MODULE_HANDLE_EX_FLAG_PIN标志可以实现类似的行为(可以在dll加载时从DllMain中调用)。

我要卸载的dll是python.dll(更准确地说是python36.dll)。但是在python源代码中没有找到这个标志的用法。 DllMain本身就是空的。

编辑2 : 我被要求提供最低限度的可执行示例 - 所以在这里: 它使用pythonnet库(版本2.3.0) - 这是PythonEngine调用。

[TestFixture]
public class PythonUnloadTest
{
    public static class DllImports
    {
        [DllImport("kernel32.dll")]
        public static extern IntPtr LoadLibrary(string dllToLoad);

        [DllImport("kernel32.dll")]
        public static extern bool FreeLibrary(IntPtr hModule);
    }

    [Test]
    public void PythonLoadUnload()
    {
        const string PythonDll = @"PythonEngine\python36";

        PythonEngine.Initialize();
        //locking etc not included for simplicity

        //Replace module with 'sys' (or some others) and dll can be unloaded
        var module = PythonEngine.ImportModule("numpy");
        module.Dispose();

        IntPtr pythonDllHandle = DllImports.LoadLibrary(PythonDll);
        if (pythonDllHandle == IntPtr.Zero)
        {
            throw new Exception("Dll not loaded");
        }

        for (int i = 0; i < 100000; i++)
        {
            if (!DllImports.FreeLibrary(pythonDllHandle))
            {
                return;
            }
        }

        Assert.Fail("Python not unloaded");
    }
}

无论这个具体情况如何(python和pythonnet以及numpy的加载) - 仍然需要有一些现象阻止进程通过调用FreeLibrary来卸载dll。我怀疑安装一些钩子或用上面提到的标志调用GetModuleHandleEx ......我会尝试检查numpy源码。但是如果有任何具体的提示我应该寻找什么 - 我会很感激那些

1 个答案:

答案 0 :(得分:1)

  

为什么FreeLibrary会重复返回true?

正如我已经编辑过的那样,原因很简单: