使用PCSC库的C# NFC项目报错:尝试结束不存在的事务
修复 "An attempt was made to end a non-existent transaction" 错误
问题根源
你的代码存在两个核心问题:
- 未启动PCSC事务:发送APDU命令前未启动事务,导致
IsoReader释放时尝试结束一个不存在的事务,触发该错误。 - 无效的初始APDU命令:直接发送
GetData命令(0xCA)不符合NFC标签交互逻辑,该命令需要先选中特定数据对象或应用才能生效。
修复步骤
1. 启动PCSC事务
创建IsoReader实例后,调用BeginTransaction()方法显式启动事务,确保释放时能正常结束事务。
2. 使用合法的初始命令
替换原有的GetData命令为ACR122U读卡器支持的获取UID命令(0xFF 0xCA 0x00 0x00 0x00),这是读取NFC标签最基础且通用的操作。
修正后的代码
using System; using PCSC; using PCSC.Iso7816; class Program { static void Main() { try { var contextFactory = ContextFactory.Instance; using (var context = contextFactory.Establish(SCardScope.System)) { var readerNames = context.GetReaders(); if (readerNames.Length == 0) { Console.WriteLine("未找到读卡器。"); return; } var readerName = readerNames[0]; Console.WriteLine($"使用读卡器:{readerName}"); using (var isoReader = new IsoReader(context, readerName, SCardShareMode.Shared, SCardProtocol.Any, false)) { Console.WriteLine($"读卡器状态:{isoReader}"); // 启动PCSC事务,解决事务结束错误 isoReader.BeginTransaction(); // 发送ACR122U专用命令获取NFC标签UID var apdu = new CommandApdu(IsoCase.Case2Short, isoReader.ActiveProtocol) { CLA = 0xFF, // 读卡器专用命令类 Instruction = 0xCA,// 获取UID指令 P1 = 0x00, P2 = 0x00, Le = 0x00 // 请求返回最大长度数据 }; Console.WriteLine($"发送APDU命令:{BitConverter.ToString(apdu.ToArray())}"); var response = isoReader.Transmit(apdu); Console.WriteLine($"响应状态:SW1={response.SW1:X2}, SW2={response.SW2:X2}"); if (response.HasData) { Console.WriteLine("NFC标签UID:"); Console.WriteLine(BitConverter.ToString(response.GetData())); } else { Console.WriteLine($"读取失败:SW1 SW2 = {response.SW1:X2} {response.SW2:X2}"); } } } } catch (Exception ex) { Console.WriteLine($"发生错误:{ex.Message}"); } } }
额外说明
- 事务管理:
IsoReader的using块会自动调用EndTransaction()方法,无需手动结束事务。 - 命令适配:如果需要读取标签内的其他数据,需根据标签类型(如MIFARE Classic/Ultralight)发送对应的APDU命令,例如MIFARE Classic需要先验证密钥再读取扇区数据。
内容的提问来源于stack exchange,提问作者user26316631
相关产品推荐
相关产品推荐

