我有一个 .Net 控制台应用程序,它使用 winscard/pcsclite 与智能卡通信。 它在 Windows 和 32 位 Linux 上没有问题,但在 64 位 Linux 上失败。 SCardTransmit 函数返回 0 但 RecvLength 没有更新,也没有收到数据。
更新:
问题似乎出在对 SCardTransmit 函数的调用中。 Dllimport 是这样指定的。 我还尝试将 recvLen 指定为 IntPtr,结果相同。
[StructLayout(LayoutKind.Sequential)]
internal struct SCardIoRequest
{
internal SCardIoRequest(CardProtocol protocol)
{
Protocol = (uint)protocol;
Length = (uint)Marshal.SizeOf(typeof(SCardIoRequest));
}
public uint Protocol;
public uint Length;
}
[DllImport("Winscard.dll", SetLastError = true)]
private static extern int SCardTransmit(IntPtr card, [In] ref SCardIoRequest sendPci, byte[] sendBuffer, uint sendLen, IntPtr recvPci, [Out] byte[] recvBuffer, ref int recvLen);
附加信息和日志:
mono version 2.10.8 pcsc-lite version 1.4.4 [centos@localhost ~]$ mono pcsctest.exe Test PC/CS SCardEstablishContext - returned 0 SCardListReaders - returned 0 SCardListReaders - returned 0 After GetReaders Reader: OmniKey CardMan 6121 00 00 SCardConnect - returned 0 Connect to Card, protocol: 2 SCardTransmit - returned 0 recvlen = 256 Serial: 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 SCardTransmit - returned 0 winscard_msg_srv.c:217:SHMProcessEventsServer() Common channel packet arrival winscard_msg_srv.c:226:SHMProcessEventsServer() SHMProcessCommonChannelRequest detects: 7 pcscdaemon.c:174:SVCServiceRunLoop() A new context thread creation is requested: 7 winscard_svc.c:131:ContextThread() Thread is started: 7 winscard_msg_srv.c:288:SHMProcessEventsContext() correctly processed client: 7 winscard_svc.c:179:ContextThread() Client is protocol version 2:2 winscard_msg_srv.c:288:SHMProcessEventsContext() correctly processed client: 7 winscard.c:242:SCardEstablishContext() Establishing Context: 16985718 winscard_msg_srv.c:288:SHMProcessEventsContext() correctly processed client: 7 winscard.c:298:SCardConnect() Attempting Connect to OmniKey CardMan 6121 00 00 using protocol: 2 prothandler.c:130:PHSetProtocol() Attempting PTS to T=1 ifdhandler.c:488:IFDHSetProtocolParameters() lun: 0, protocol T=1 winscard.c:433:SCardConnect() Active Protocol: T=1 winscard.c:443:SCardConnect() hCard Identity: eaf1 winscard_msg_srv.c:288:SHMProcessEventsContext() correctly processed client: 7 winscard_svc.c:730:MSGCheckHandleAssociation() Client failed to authenticate winscard_msg_srv.c:288:SHMProcessEventsContext() correctly processed client: 7 winscard_svc.c:730:MSGCheckHandleAssociation() Client failed to authenticate winscard_msg_srv.c:288:SHMProcessEventsContext() correctly processed client: 7 winscard_svc.c:730:MSGCheckHandleAssociation() Client failed to authenticate winscard_msg_srv.c:288:SHMProcessEventsContext() correctly processed client: 7 winscard_svc.c:730:MSGCheckHandleAssociation() Client failed to authenticate winscard_msg_srv.c:288:SHMProcessEventsContext() correctly processed client: 7 winscard_svc.c:730:MSGCheckHandleAssociation() Client failed to authenticate winscard_msg_srv.c:288:SHMProcessEventsContext() correctly processed client: 7 winscard.c:253:SCardReleaseContext() Releasing Context: 16985718 winscard.c:848:SCardDisconnect() Active Contexts: 1 winscard_msg_srv.c:276:SHMProcessEventsContext() Client has disappeared: 7 winscard_svc.c:144:ContextThread() Client die: 7
最佳答案
您没有发布您的代码,所以这只是一个猜测,但看起来问题出在您的互操作代码中,该代码指定如何在托管 - C# - 和非托管 - C - 内存之间编码(marshal)数据。您很可能面临 famous C 'long' type marshaling problem我在开发多平台 Pkcs11Interop 项目时也遇到过。
PCSC API 使用 C 的“long”类型,这种类型很难编码,因为 .NET 中没有类型可以在所有平台上匹配其大小。问题在于 C 的“long”类型在某些平台(Win32、Win64 和 Unix32)上可以是 4 个字节长,同时在其他平台(Unix64)上可以是 8 个字节长。在 .NET 中,无论平台如何,都有 4 个字节长的“int”类型,无论平台如何,都有 8 个字节长的“long”类型。它们都不能用作 C 'long' 类型的多平台替代方案,唯一的解决方案是使用和编码两组不同的函数和结构,其中一组具有 'int' .NET 类型用于 C 'long' 类型的平台是 4 个字节长,另一个是 'long' .NET 类型,用于 C 'long' 类型是 8 个字节长的平台。
总结一下:您应该修复您的编码(marshal)处理代码,或者您应该使用更好管理的 PCSC 互操作库,该库还支持 C“long”类型为 8 字节长的平台。看起来像 pcsc-sharp可能是一种方法,但我还没有测试过。
关于c# - 在 64 位 Linux 上使用单声道调用 pcsclite,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23010818/