c# - 在 64 位 Linux 上使用单声道调用 pcsclite

标签 c# .net linux mono

我有一个 .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/

相关文章:

c# - .NET 任务/TPL 测试和模拟? (或者用法不正确?)

linux - 如何从 Linux 计算机挂起 Hyper-V VM?

linux - 无需重启即可升级 - 实践中会出现哪些问题?

linux - 自动化 Enter 按键不适用于 Linux Mint 15

c# - 处理程序未捕获未处理的异常

C# - 检查 JSON 结构是否更改

c# - 我应该使用哪个 .net 图表库?

.net - 使用.Net ServiceInstaller在服务安装上设置 'Start Parameters'吗?

c# - 如何在 Windows 机器上为 Linux 编译 .NET Core 应用程序

c# - 在 XNA 中绘制二维曲线