使用C#動態載入DLL檔案
阿新 • • 發佈:2019-01-14
**
使用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);