C#如何載入嵌入到資源的非託管dll

RyzenAdorer發表於2021-05-15

如何載入非託管Dll

我們總會遇到需要載入非Win32的非託管dll,這裡推薦一種方式就是將那些非win32的非託管dll嵌入資源的方式,在入口解壓並且載入的方式,我先來看看如何實現吧,首先我們準備好demo,新增控制檯專案如下:

程式碼如下:

        static void Main(string[] args)
        {
            UnzipAndLoad();
        }

        /// <summary>
        /// 解壓資源並且載入非託管DLL
        /// </summary>
        static void UnzipAndLoad()
        {
            var folderPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
            var dllPath = Path.Combine(folderPath, $"{nameof(Resource.pdfium)}.dll");//解壓輸出的路徑
            if (!File.Exists(dllPath))
                File.WriteAllBytes(dllPath, Resource.pdfium);
            LoadDll(dllPath);//應該每次都載入非託管
        }

        /// <summary>
        /// 載入非託管DLL
        /// </summary>
        /// <param name="dllName"></param>
        public static void LoadDll(string dllName)
        {
            IntPtr h = LoadLibrary(dllName);
            if (h == IntPtr.Zero)
            {
                Exception e = new Win32Exception();
                throw new DllNotFoundException($"Unable to load library: {dllName}", e);
            }

            Console.WriteLine("Load library successful");
        }

        [DllImport("kernel32", SetLastError = true, CharSet = CharSet.Unicode)]
        static extern IntPtr LoadLibrary(string lpFileName);

輸出:

Load library successful

其實上述程式碼還有優化的空間,微軟整合了很多win32函式的包,例如我們要匯入win32的下常見的kernel32dll和user32dll,我們可以通過nuget安裝,我們可以在csproj加入以下程式碼(或者直接nuget搜尋PInvoke.Kernel32):

  <ItemGroup>
        <PackageReference Include="PInvoke.Kernel32" Version="0.7.104" />
  </ItemGroup>

那麼之前的程式碼刪除的LoadLibrary方法刪除,LoadDll方法則直接改為以下:

    /// <summary>
    /// 載入非託管DLL
    /// </summary>
    /// <param name="dllName"></param>
    public static void LoadDll(string dllName)
    {
        var h =Kernel32.LoadLibrary(dllName);
        if (h.IsInvalid)//是否是無效的
        {
            Exception e = new Win32Exception();
            throw new DllNotFoundException($"Unable to load library: {dllName}", e);
        }
        Console.WriteLine("Load library successful");
    }

參考

https://blog.lindexi.com/post/%E6%8E%A8%E8%8D%90%E5%AE%98%E6%96%B9%E5%BC%80%E6%BA%90-PInvoke-%E5%BA%93-%E5%8C%85%E5%90%AB%E5%A4%A7%E9%87%8F-win32-%E5%B0%81%E8%A3%85.html

相關文章