由於項目需要,我必須使用C#來操作讀卡器,讀卡器只提供了幾個可供調用的DLL文件,並沒呀給出例程之類的資源,雖然我認為這個讀卡器廠商非常失敗,但是我也只能耐著性子做完這件事情。
我們在使用C++的時候,對動態鏈接庫的操作是非常方便的,只要使用LoadLibrary()就可以很簡單的調用該DLL文件中所包含的函數。但是使用.NET 2.0就不那麼容易了,由於本人使用C#,所以以C#代碼為例與大家共享如何在.Net平台下對DLL文件進行調用。
1.使用DLL函數查看器對讀卡器廠商提供的DLL文件進行了分析。找出了函數名,和DLL的依賴關系。DLL的依賴關系非常重要,我們必須找到ghc715.dll依賴的DLL文件,並且在加載動態鏈接庫的時候必須先將依賴的DLL加載到系統中,才能保證我們對讀卡器可以進行操作。
2.using System.Runtime.InteropServices;該命名空間提供各種各樣支持 COM interop 及平台調用服務的成員。主要是用於與非托管代碼之間的交互。該命名空間中=最重要的屬性有 DllImportAttribute(可以用來定義用於訪問非托管 API 的平台調用方法)和 MarshalAsAttribute(可以用來指定如何在托管內存與非托管內存之間封送數據)。 詳見http://msdn2.microsoft.com/zh-cn/library/system.runtime.interopservices(VS.80).ASPx
3.由於讀卡器提供的DLL文件無法在系統內注冊,所以我們只能采用動態加載的方法來完成這一工作。使用了如下幾個Windows 的 API:
1. Loadlibrary: 裝載指定DLL動態庫
2. GetProcAddress:獲得函數的入口地址
3. Freelibrary: 從內存中卸載動態庫
為了完成調用GetProcAddress返回的函數地址,我們使用了Marshal.GetDelegateForFunctionPointer方法,該方法將非托管函數的指針轉換為委托。
看到這些知識,剩下的事情就簡單了,我把所有對讀卡器的操作封裝成了一個類,提供兩個public 函數,一個是Read(讀卡)另外一個就是Write(寫卡)。並把類的主要結構寫到下面,僅供參考,希望有高人給出一些指點意見。
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace QL.Card
{
public class Card
{
#region Win API 聲明調用kernel.dll中的三個方法
[DllImport("kernel32.dll")]
private extern static IntPtr LoadLibrary(string path);
[DllImport("kernel32.dll")]
private extern static IntPtr GetProcAddress(IntPtr lib, string funcName);
[DllImport("kernel32.dll")]
private extern static bool FreeLibrary(IntPtr lib);
[DllImport("kernel32.dll")]
public static extern IntPtr GetStdHandle(int nStdHandle);
const int STD_OUTPUT_HANDLE = -11;
#endregion
private IntPtr hLib;
private IntPtr otherlib1;
private IntPtr otherlib2;
public (String DLLPath)
{
otherlib1 = LoadLibrary("MFC42D.dll");
otherlib2 = LoadLibrary("MSVCRTD.dll");
hLib = LoadLibrary(DLLPath); }
~DllInvoke()
{
FreeLibrary(hLib);
FreeLibrary(otherlib2);
FreeLibrary(ot
herlib1);
}
//將要執行的函數轉換為委托
public Delegate Invoke (string APIName,Type t)
{
IntPtr api = GetProcAddress(hLib, APIName);
return (Delegate)Marshal.GetDelegateForFunctionPointer(api, t);
}
//這裡將DLL裡要調用的函數聲明為委托,其中int為該函數的返回值
public delegate int readcard(//參數列表);
public delegate int writecard(//參數列表);
public string Read()
{
Carder dll = new Carder(Environment.CurrentDirectory + "\\ghc715.dll");
string mdata1 = "";
string mdata2 = "";
string error = "";
readcard rc = (readcard)dll.Invoke("readcard", typeof(readcard)); int rcCode = rc(1, 2, out mdata1, out mdata2, 2);
//接下來是一些錯誤處理
}
public string Write(string input)
{
Carder dll = new Carder(Environment.CurrentDirectory + "ghc715.dll");
&n
int rcCode = rc(1, 2, mdata1,mdata2, 2);
//錯誤處理
}
}
}
就這麼多了,希望大家多多指教!