在 Web 專案中整合 RFID 讀卡器,傳統方案多採用 VC++ 或 VB6 開發 ActiveX 控制項。考慮到團隊對 C# 技術棧的熟悉度,本文採用 Windows Forms Control → COM Interop → ActiveX 的路徑,以 C# 快速構建可在 IE 中運行的 RFID 讀卡元件。
<object> 標籤引用針對廠商提供的 MasterRD.dll 進行 P/Invoke 宣告:
using System;
using System.Runtime.InteropServices;
namespace RFIDReader {
public class ReadRfid {
[DllImport("MasterRD.dll")] private static extern int rf_init_com(int port, int baud);
[DllImport("MasterRD.dll")] private static extern int rf_request(short icdev, byte model, ref short TagType);
[DllImport("MasterRD.dll")] private static extern int rf_anticoll(short icdev, byte bcnt, ref byte PPSnr, ref byte pRLength);
[DllImport("MasterRD.dll")] private static extern int rf_ClosePort();
public string CardNum {
get { return getCardNum(); }
}
private string getCardNum() {
int port = 4, baud = 9600; // COM4, 9600bps
byte model = 0x52; short tagType = 0; byte bcnt = 4;
byte[] buf = new byte[200];
try {
rf_init_com(port, baud);
rf_request(0, model, ref tagType);
rf_anticoll(0, bcnt, ref buf[0], ref bcnt);
rf_ClosePort();
string sn = "";
for (int i = 0; i < bcnt; i++) sn += Convert.ToString(buf[i], 16).ToUpper().PadLeft(2, '0');
if (sn == "0000") throw new Exception("讀取失敗");
return sn;
} catch { return ""; }
}
}
}
實作 IObjectSafety 讓 IE 信任控制項可安全載入:
[ComImport, Guid("CB5BDC81-93C1-11CF-8F20-00805F2CD064"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IObjectSafety {
[PreserveSig] void GetInterfaceSafetyOptions(ref Guid riid, out int pdwSupportedOptions, out int pdwEnabledOptions);
[PreserveSig] void SetInterfaceSafetyOptions(ref Guid riid, int dwOptionSetMask, int dwEnabledOptions);
}
[Guid("0CBD6597-3953-4B88-8C9F-F58B1B023413"),
ProgId("RFIDReader.Reader"),
ComVisible(true)]
public partial class Reader : UserControl, IObjectSafety {
private Timer timer1 = new Timer();
private ReadRfid rfid = new ReadRfid();
public Reader() { InitializeComponent(); timer1.Tick += Timer1_Tick; }
public int TimerSpan { get => timer1.Interval; set => timer1.Interval = value; }
public string CardNum { get => textBox1.Text; }
public void GetInterfaceSafetyOptions(ref Guid riid, out int pdwSupportedOptions, out int pdwEnabledOptions) {
pdwSupportedOptions = 1; pdwEnabledOptions = 2; // INTERFACESAFE_FOR_UNTRUSTED_CALLER/ DATA
}
public void SetInterfaceSafetyOptions(ref Guid riid, int dwOptionSetMask, int dwEnabledOptions) { /* 不拋異常即視為信任 */ }
private void Timer1_Tick(object sender, EventArgs e) {
string sn = rfid.CardNum;
if (!string.IsNullOrEmpty(sn)) { textBox1.Text = sn; GetInfo(); }
}
private void GetInfo() { label1.Text = "卡片已讀取"; }
}
在 AssemblyInfo.cs 加入:
[assembly: AllowPartiallyTrustedCallers()]
[assembly: ComVisible(true)]
專案屬性 → Build → 勾選 Register for COM interop;並簽署強名稱金鑰(.snk)。
ReaderInstaller.msiinstall.inf:[version]
signature="$CHICAGO$"
AdvancedINF=2.0
[Setup Hooks]
hook1=hook1
[hook1]
run=msiexec.exe /i "%EXTRACT_DIR%\ReaderInstaller.msi" /qn
cabarc.exe 打包:cabarc n RFIDReader.cab ReaderInstaller.msi install.inf<object id="RFIDReader" classid="clsid:0CBD6597-3953-4B88-8C9F-F58B1B023413"
codebase="RFID/RFIDReader.cab"></object>
classid 必須與 GuidAttribute 一致