在64位Linux上使用mono调用pcsclite

时间:2014-04-11 11:04:04

标签: 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

1 个答案:

答案 0 :(得分:2)

你没有发布你的代码,所以这只是猜测,但看起来你的互操作代码中的问题是指定数据如何在托管 - C# - 和非托管 - C - 内存之间编组。你很可能面对我在多平台Pkcs11Interop项目开发过程中遇到的famous C 'long' type marshaling problem

PCSC API使用C'long'类型,这种类型非常难以编组,因为.NET中没有与所有平台上的大小相匹配的类型。问题是在某些平台(Win32,Win64和Unix32)上C'long'类型可以是4个字节长,同时在其他平台(Unix64)上它可以是8个字节长。在.NET中有'int'类型,无论平台如何都是4字节长,并且有'long'类型,无论平台如何都是8字节长。它们都不能用作C'long'类型的多平台替代方案,唯一的解决方案是使用和编组两组不同的函数和结构,一个用'int'.NET类型用于C'long'类型的平台长度为4个字节,另一个为“long”.NET类型,用于C'long'类型为8个字节长的平台。

总结一下:你应该修复你的编组代码,或者你应该使用更好的托管PCSC互操作库,它也支持C'long'类型长度为8个字节的平台。看起来pcsc-sharp可能是一种方式,但我还没有测试过它。