为何我的C# RFID读取卡片UID与ATR响应代码无法运行?
排查OMNIKEY 5022读取UID/ATR无响应的问题
核心问题排查点
读卡器数量判断逻辑过于严苛
代码中if(readernames.Length == 1)限制必须只有1个读卡器才执行后续逻辑,但实际系统中可能存在虚拟读卡器、蓝牙读卡器等其他设备,导致直接跳过核心执行流程。应改为判断读卡器数组是否非空,而非固定长度为1。未处理连接/操作失败的反馈
代码仅在操作成功时执行赋值,失败时无任何提示,无法定位是读卡器未连接、卡片未放置还是协议错误。需在每一步操作失败时,输出可读的错误描述,比如使用SCardHelper.StringifyError(readerError)获取具体错误信息。资源未正确释放
SCardContext和SCardReader属于非托管资源,未用using语句包裹可能导致资源泄漏,后续操作无法正常调用读卡器。ATR长度判断可能误判有效数据
ATR.Length > 2的条件可能过滤掉部分短ATR的合法卡片,建议调整为ATR != null && ATR.Length > 0。Transmit操作未处理无卡片的情况
如果执行Transmit时阅读器上没有卡片,会直接失败但无提示,需提前判断卡片是否存在,或在失败时输出错误。
修复后的代码示例
using System; using PCSC; using PCSC.Iso7816; using System.Linq; using System.Windows.Forms; namespace TestApplication { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { try { // 使用using自动释放非托管资源 using (var ctx = new SCardContext()) { ctx.Establish(SCardScope.System); var readernames = ctx.GetReaders(); // 优先判断是否存在可用读卡器 if (readernames.Length == 0) { MessageBox.Show("未检测到任何读卡器", "提示"); return; } // 取第一个可用读卡器(可扩展为让用户选择) var readername = readernames[0]; using (var RFIDReader = new SCardReader(ctx)) { var readerError = RFIDReader.Connect(readername, SCardShareMode.Shared, SCardProtocol.Any); if (readerError != SCardError.Success) { MessageBox.Show($"读卡器连接失败:{SCardHelper.StringifyError(readerError)}", "错误"); return; } // 获取ATR值 byte[] ATR; readerError = RFIDReader.GetAttrib(SCardAttribute.AtrString, out ATR); if (readerError == SCardError.Success && ATR != null && ATR.Length > 0) { var atrStr = BitConverter.ToString(ATR).Replace("-", " "); textBox1.Text = atrStr; } else { MessageBox.Show($"获取ATR失败:{SCardHelper.StringifyError(readerError)}", "错误"); } // 获取UID值(过滤响应末尾的状态字) var sendBytes = new byte[] { 0xFF, 0xCA, 0x00, 0x00, 0x00 }; var recvBytes = new byte[35]; readerError = RFIDReader.Transmit(sendBytes, ref recvBytes); if (readerError == SCardError.Success) { var uidBytes = recvBytes.Take(recvBytes.Length - 2).ToArray(); var uidStr = BitConverter.ToString(uidBytes).Replace("-", " ").Trim(); textBox2.Text = uidStr; } else { MessageBox.Show($"获取UID失败:{SCardHelper.StringifyError(readerError)}", "错误"); } RFIDReader.Disconnect(SCardReaderDisposition.Reset); } } } catch (Exception ex) { MessageBox.Show($"异常信息:{ex.Message}\n调用栈:{ex.StackTrace}", "错误"); } } } }
额外检查项
- 确认OMNIKEY 5022的驱动已正确安装,可通过设备管理器查看是否有黄色感叹号
- 测试时确保卡片完全放置在阅读器感应区域内
- 若系统中有多个读卡器,可添加下拉框让用户手动选择目标设备,避免选错
内容的提问来源于stack exchange,提问作者Buchi
相关产品推荐
相关产品推荐

