1. 程式人生 > >使用C#動態載入DLL檔案

使用C#動態載入DLL檔案

**

使用C#動態載入DLL檔案

**

1.首先用到kernel32.dll API函式,對於C#來說呼叫windows API 還是蠻簡單的事件。只需要宣告一下就可以了。

    //載入DLL
    [DllImport("kernel32.dll", SetLastError = true ,CharSet = CharSet.Auto)]
    private extern static IntPtr LoadLibrary(string path);
   
    //獲取函式地址
    [DllImport("kernel32.dll",SetLastError =true)]
    private extern static IntPtr GetProcAddress(IntPtr lib, string funcName);

   //釋放相應的庫
    [DllImport("kernel32.dll")]
    private extern static bool FreeLibrary(IntPtr lib);

    //獲取錯誤資訊
    [DllImport("Kernel32.dll")]
    public extern static int FormatMessage(int flag, ref IntPtr source, int msgid, int langid, ref string buf, int size, ref IntPtr args);

2.需要知道你呼叫DLL裡面的函式名稱,以下是主要的三個函式。

        /// <summary>
        /// 建構函式
        /// </summary>
        /// <param name="dll_path">DLL路徑</param>
        public DllInvoke(string dll_path)
        {
            if (File.Exists(dll_path))
            {
                hLib = LoadLibrary(dll_path);
            }
        }

        /// <summary>
        /// 解構函式
        /// </summary>
        ~DllInvoke()
        {
            FreeLibrary(hLib);
        }

        /// <summary>
        /// 將要執行的函式轉換為委託
        /// </summary>
        /// <param name="APIName">函式名稱</param>
        /// <param name="t">型別</param>
        /// <returns></returns>
        public Delegate Invoke(string APIName, Type t)
        {
            IntPtr api = GetProcAddress(hLib, APIName);
            return Marshal.GetDelegateForFunctionPointer(api, t);
        }

我將呼叫API的函式封裝成類。
在除錯的過程遇到載入不成功的情況,然後想到獲取錯誤程式碼,然後從錯誤程式碼裡面查詢到原因。函式如下:

        /// <summary>
        /// 獲取系統錯誤資訊描述
        /// </summary>
        /// <param name="errCode">系統錯誤碼</param>
        /// <returns></returns>
        public string GetSysErrMsg(int errCode)
        {
            IntPtr tempptr = IntPtr.Zero;
            string msg = null;
            FormatMessage(0x1300, ref tempptr, errCode, 0, ref msg, 255, ref tempptr);
            return msg;
        }

        /// <summary>
        /// 獲取最近一個win32Error
        /// </summary>
        /// <returns></returns>
        public int GetWin32ErrorCode()
        {
            return Marshal.GetLastWin32Error();
        }

3.在程式中呼叫DLL的例子
定義委託:

[UnmanagedFunctionPointerAttribute(CallingConvention.StdCall)]
 private delegate int GETMD5(string str, byte[] pData);

例項化物件:

                DllInvoke dll = new DllInvoke(System.AppDomain.CurrentDomain.BaseDirectory + "\\md5.dll");
                //根據函式名獲取函式委託物件 [email protected]函式的別名
                GETMD5 get_md5 = (GETMD5)dll.Invoke("[email protected]", typeof(GETMD5));
                //temp輸出物件
                get_md5(“123456789”, temp);