C#使用FreeLibrary卸载C ++非托管DLL的动态加载不会解锁文件

时间:2017-05-10 23:11:17

标签: c# c++ websocket pinvoke boost-asio

我有一个C#程序,它使用LoadLibrary加载一个非托管C ++ DLL,然后用FreeLibrary卸载它。应用程序运行正常,我可以在C#应用程序中随意加载,卸载和文件级替换DLL。

对于某些(新的)原因,现在当我使用FreeLibrary DLL时,它成功地从C#卸载(我从FreeLibrary获得正值返回值),但* .dll文件仍然被文件系统锁定而且我'我无法更新它的新版本(这是使用动态加载的全部原因)。

该应用程序使用带有Beast websockets的Boost ASIO,我最近做的更改是切换到SSL。我认为我是如何调用或关闭SSL文件系统锁定DLL的连接有问题。但由于FreeLibrary返回成功(以及后续调用FreeLibrary挂起),我不确定为什么DLL文件仍会被锁定。

以下是我在C#(代码段)中加载DLL的方法:

    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern IntPtr LoadLibrary(string libname);

    [DllImport("kernel32.dll")]
    private static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);

    [DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
    private static extern bool FreeLibrary(IntPtr hModule);

    IntPtr Handle;

    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    private delegate void Initdb();
    Initdb InitdbFunction;

主要

    Handle = LoadLibrary("Perks.dll");
    if (Handle == IntPtr.Zero) {
        int errorCode = Marshal.GetLastWin32Error();
        throw new Exception(string.Format("Failed to load library (ErrorCode: {0})", errorCode));
    }
    IntPtr funcaddr;

    funcaddr = GetProcAddress(Handle, "Initdb");
    InitdbFunction = Marshal.GetDelegateForFunctionPointer(funcaddr, typeof(Initdb)) as Initdb;

卸载功能

    if (FreeLibrary(Handle))
    {
        Console.WriteLine("FreeLibrary true");
    }
    else
    {
        Console.WriteLine("FreeLibrary false");
    }
    Handle = IntPtr.Zero;

我在非托管DLL中的新增Boost ASIO和Beast websockets(可能会以某种方式引起问题)就在这里C ++(片段)

    std::string                     wsm_SERVER_URL;
    boost::asio::io_service         wsm_ios;
    boost::asio::io_service::work   wsm_work{ wsm_ios };
    boost::asio::ip::tcp::resolver  wsm_r{ wsm_ios };
    boost::asio::ip::tcp::socket    wsm_sock{ wsm_ios };
    std::unique_ptr<beast::websocket::stream< boost::asio::ssl::stream<boost::asio::ip::tcp::socket>>> wsm_client;
    boost::asio::ssl::context wsm_ctx{ boost::asio::ssl::context::sslv23 };

初​​始化

    wsm_client = std::make_unique<beast::websocket::stream<boost::asio::ssl::stream<boost::asio::ip::tcp::socket>>>(wsm_ios, wsm_ctx);

使用

    wsm_client = std::make_unique<beast::websocket::stream<boost::asio::ssl::stream<boost::asio::ip::tcp::socket>>>(wsm_ios, wsm_ctx);
    boost::asio::ip::tcp::resolver::iterator iter = wsm_r.resolve(boost::asio::ip::tcp::resolver::query{ wsm_SERVER_URL, "https" });
    const boost::asio::ip::tcp::endpoint EP = iter->endpoint();
    boost::system::error_code EC;
    wsm_client->next_layer().next_layer().connect(EP, EC);
    wsm_client->next_layer().set_verify_mode(boost::asio::ssl::verify_none);
    wsm_client->next_layer().handshake(boost::asio::ssl::stream_base::client);
    wsm_client->handshake(wsm_SERVER_URL, srv_url);

停用(在C#执行FreeLibrary部分之前在C ++中调用)

wsm_client->next_layer().next_layer().close();
wsm_client->next_layer().next_layer().cancel();
wsm_client->close(beast::websocket::close_code::normal);
wsm_client.reset();
wsm_ios.stop();

0 个答案:

没有答案