首页 > 解决方案 > 任何人都在 .net 5.0 中为 SCardListReaders 使用 smartcardmagic.net 库

问题描述

有人在.net 5.0 中使用过智能卡magic.net 库吗? http://www.smartcard-magic.net/en/pc-sc-reader/csharppcsc-wrapper/ 我有一个.net 4.8,它能够成功连接到Acr122U读卡器。

我尝试使用的课程是

使用 System.Runtime.InteropServices;

namespace TestApp
{
    public class WinsCardWrapper
    {
        [StructLayout(LayoutKind.Sequential)]
        public struct ScardIoRequest
        {
            public int dwProtocol;
            public int cbPciLength;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct ApduRec
        {
            public byte bCLA;
            public byte bINS;
            public byte bP1;
            public byte bP2;
            public byte bP3;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
            public byte[] Data;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
            public byte[] SW;
            public bool IsSend;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct ScardReaderstate
        {
            public string RdrName;
            public int UserData;
            public int RdrCurrState;
            public int RdrEventState;
            public int ATRLength;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 37)]
            public byte ATRValue;
        }

        public const int ScardSuccess = 0;
        public const int ScardAtrLength = 33;


        /* ===========================================================
        '  Memory Card type constants
        '===========================================================*/
        public const int CT_MCU = 0x00;                   // MCU
        public const int CT_IIC_Auto = 0x01;               // IIC (Auto Detect Memory Size)
        public const int CT_IIC_1K = 0x02;                 // IIC (1K)
        public const int CT_IIC_2K = 0x03;                 // IIC (2K)
        public const int CT_IIC_4K = 0x04;                 // IIC (4K)
        public const int CT_IIC_8K = 0x05;                 // IIC (8K)
        public const int CT_IIC_16K = 0x06;                // IIC (16K)
        public const int CT_IIC_32K = 0x07;                // IIC (32K)
        public const int CT_IIC_64K = 0x08;                // IIC (64K)
        public const int CT_IIC_128K = 0x09;               // IIC (128K)
        public const int CT_IIC_256K = 0x0A;               // IIC (256K)
        public const int CT_IIC_512K = 0x0B;               // IIC (512K)
        public const int CT_IIC_1024K = 0x0C;              // IIC (1024K)
        public const int CT_AT88SC153 = 0x0D;              // AT88SC153
        public const int CT_AT88SC1608 = 0x0E;             // AT88SC1608
        public const int CT_SLE4418 = 0x0F;                // SLE4418
        public const int CT_SLE4428 = 0x10;                // SLE4428
        public const int CT_SLE4432 = 0x11;                // SLE4432
        public const int CT_SLE4442 = 0x12;                // SLE4442
        public const int CT_SLE4406 = 0x13;                // SLE4406
        public const int CT_SLE4436 = 0x14;                // SLE4436
        public const int CT_SLE5536 = 0x15;                // SLE5536
        public const int CT_MCUT0 = 0x16;                  // MCU T=0
        public const int CT_MCUT1 = 0x17;                  // MCU T=1
        public const int CT_MCU_Auto = 0x18;               // MCU Autodetect

        public enum SCARD_SCOPE
        {
            USER = 0,
            TERMINAL = 1,
            SYSTEM = 2
        }

        /*===============================================================
        ' CONTEXT SCOPE
        =============================================================== */
        public const int SCARD_SCOPE_USER = 0;
        /*===============================================================
        ' The context is a user context, and any database operations 
        '  are performed within the domain of the user.
        '===============================================================*/
        public const int SCARD_SCOPE_TERMINAL = 1;
        /*===============================================================
        ' The context is that of the current terminal, and any database 
        'operations are performed within the domain of that terminal.  
        '(The calling application must have appropriate access permissions 
        'for any database actions.)
        '===============================================================*/

        public const int SCARD_SCOPE_SYSTEM = 2;
        /*===============================================================
        ' The context is the system context, and any database operations 
        ' are performed within the domain of the system.  (The calling
        ' application must have appropriate access permissions for any 
        ' database actions.)
        '===============================================================*/
        /*=============================================================== 
        ' Context Scope
        '===============================================================*/
        public const int SCARD_STATE_UNAWARE = 0x00;
        /*===============================================================
        ' The application is unaware of the current state, and would like 
        ' to know. The use of this value results in an immediate return
        ' from state transition monitoring services. This is represented
        ' by all bits set to zero.
        '===============================================================*/
        public const int SCARD_STATE_IGNORE = 0x01;
        /*===============================================================
        ' The application requested that this reader be ignored. No other
        ' bits will be set.
        '===============================================================*/

        public const int SCARD_STATE_CHANGED = 0x02;
        /*===============================================================
        ' This implies that there is a difference between the state 
        ' believed by the application, and the state known by the Service
        ' Manager.When this bit is set, the application may assume a
        ' significant state change has occurred on this reader.
        '===============================================================*/

        public const int SCARD_STATE_UNKNOWN = 0x04;
        /*===============================================================
        ' This implies that the given reader name is not recognized by
        ' the Service Manager. If this bit is set, then SCARD_STATE_CHANGED
        ' and SCARD_STATE_IGNORE will also be set.
        '===============================================================*/
        public const int SCARD_STATE_UNAVAILABLE = 0x08;
        /*===============================================================
        ' This implies that the actual state of this reader is not
        ' available. If this bit is set, then all the following bits are
        ' clear.
        '===============================================================*/
        public const int SCARD_STATE_EMPTY = 0x10;
        /*===============================================================
        '  This implies that there is not card in the reader.  If this bit
        '  is set, all the following bits will be clear.
         ===============================================================*/
        public const int SCARD_STATE_PRESENT = 0x20;
        /*===============================================================
        '  This implies that there is a card in the reader.
         ===============================================================*/
        public const int SCARD_STATE_ATRMATCH = 0x40;
        /*===============================================================
        '  This implies that there is a card in the reader with an ATR
        '  matching one of the target cards. If this bit is set,
        '  SCARD_STATE_PRESENT will also be set.  This bit is only returned
        '  on the SCardLocateCard() service.
         ===============================================================*/
        public const int SCARD_STATE_EXCLUSIVE = 0x80;
        /*===============================================================
        '  This implies that the card in the reader is allocated for 
        '  exclusive use by another application. If this bit is set,
        '  SCARD_STATE_PRESENT will also be set.
         ===============================================================*/
        public const int SCARD_STATE_INUSE = 0x100;
        /*===============================================================
        '  This implies that the card in the reader is in use by one or 
        '  more other applications, but may be connected to in shared mode. 
        '  If this bit is set, SCARD_STATE_PRESENT will also be set.
         ===============================================================*/
        public const int SCARD_STATE_MUTE = 0x200;
        /*===============================================================
        '  This implies that the card in the reader is unresponsive or not
        '  supported by the reader or software.
        ' ===============================================================*/
        public const int SCARD_STATE_UNPOWERED = 0x400;
        /*===============================================================
        '  This implies that the card in the reader has not been powered up.
        ' ===============================================================*/

        public const int SCARD_SHARE_EXCLUSIVE = 1;
        /*===============================================================
        ' This application is not willing to share this card with other 
        'applications.
        '===============================================================*/
        public const int SCARD_SHARE_SHARED = 2;
        /*===============================================================
        ' This application is willing to share this card with other 
        'applications.
        '===============================================================*/
        public const int SCARD_SHARE_DIRECT = 3;
        /*===============================================================
        ' This application demands direct control of the reader, so it 
        ' is not available to other applications.
        '===============================================================*/

        /*===========================================================
        '   Disposition
        '===========================================================*/
        public const int SCARD_LEAVE_CARD = 0;   // Don't do anything special on close
        public const int SCARD_RESET_CARD = 1;   // Reset the card on close
        public const int SCARD_UNPOWER_CARD = 2;   // Power down the card on close
        public const int SCARD_EJECT_CARD = 3;   // Eject the card on close


        /* ===========================================================
        ' ACS IOCTL class
        '===========================================================*/
        public const long FILE_DEVICE_SMARTCARD = 0x310000; // Reader action IOCTLs

        public const long IOCTL_SMARTCARD_DIRECT = FILE_DEVICE_SMARTCARD + 2050 * 4;
        public const long IOCTL_SMARTCARD_SELECT_SLOT = FILE_DEVICE_SMARTCARD + 2051 * 4;
        public const long IOCTL_SMARTCARD_DRAW_LCDBMP = FILE_DEVICE_SMARTCARD + 2052 * 4;
        public const long IOCTL_SMARTCARD_DISPLAY_LCD = FILE_DEVICE_SMARTCARD + 2053 * 4;
        public const long IOCTL_SMARTCARD_CLR_LCD = FILE_DEVICE_SMARTCARD + 2054 * 4;
        public const long IOCTL_SMARTCARD_READ_KEYPAD = FILE_DEVICE_SMARTCARD + 2055 * 4;
        public const long IOCTL_SMARTCARD_READ_RTC = FILE_DEVICE_SMARTCARD + 2057 * 4;
        public const long IOCTL_SMARTCARD_SET_RTC = FILE_DEVICE_SMARTCARD + 2058 * 4;
        public const long IOCTL_SMARTCARD_SET_OPTION = FILE_DEVICE_SMARTCARD + 2059 * 4;
        public const long IOCTL_SMARTCARD_SET_LED = FILE_DEVICE_SMARTCARD + 2060 * 4;
        public const long IOCTL_SMARTCARD_LOAD_KEY = FILE_DEVICE_SMARTCARD + 2062 * 4;
        public const long IOCTL_SMARTCARD_READ_EEPROM = FILE_DEVICE_SMARTCARD + 2065 * 4;
        public const long IOCTL_SMARTCARD_WRITE_EEPROM = FILE_DEVICE_SMARTCARD + 2066 * 4;
        public const long IOCTL_SMARTCARD_GET_VERSION = FILE_DEVICE_SMARTCARD + 2067 * 4;
        public const long IOCTL_SMARTCARD_GET_READER_INFO = FILE_DEVICE_SMARTCARD + 2051 * 4;
        public const long IOCTL_SMARTCARD_SET_CARD_TYPE = FILE_DEVICE_SMARTCARD + 2060 * 4;
        public const long IOCTL_SMARTCARD_ACR128_ESCAPE_COMMAND = FILE_DEVICE_SMARTCARD + 2079 * 4;

        /*===========================================================
        '   Error Codes
        '===========================================================*/
        public const int SCARD_F_INTERNAL_ERROR = -2146435071;
        public const int SCARD_E_CANCELLED = -2146435070;
        public const int SCARD_E_INVALID_HANDLE = -2146435069;
        public const int SCARD_E_INVALID_PARAMETER = -2146435068;
        public const int SCARD_E_INVALID_TARGET = -2146435067;
        public const int SCARD_E_NO_MEMORY = -2146435066;
        public const int SCARD_F_WAITED_TOO_LONG = -2146435065;
        public const int SCARD_E_INSUFFICIENT_BUFFER = -2146435064;
        public const int SCARD_E_UNKNOWN_READER = -2146435063;


        public const int SCARD_E_TIMEOUT = -2146435062;
        public const int SCARD_E_SHARING_VIOLATION = -2146435061;
        public const int SCARD_E_NO_SMARTCARD = -2146435060;
        public const int SCARD_E_UNKNOWN_CARD = -2146435059;
        public const int SCARD_E_CANT_DISPOSE = -2146435058;
        public const int SCARD_E_PROTO_MISMATCH = -2146435057;


        public const int SCARD_E_NOT_READY = -2146435056;
        public const int SCARD_E_INVALID_VALUE = -2146435055;
        public const int SCARD_E_SYSTEM_CANCELLED = -2146435054;
        public const int SCARD_F_COMM_ERROR = -2146435053;
        public const int SCARD_F_UNKNOWN_ERROR = -2146435052;
        public const int SCARD_E_INVALID_ATR = -2146435051;
        public const int SCARD_E_NOT_TRANSACTED = -2146435050;
        public const int SCARD_E_READER_UNAVAILABLE = -2146435049;
        public const int SCARD_P_SHUTDOWN = -2146435048;
        public const int SCARD_E_PCI_TOO_SMALL = -2146435047;

        public const int SCARD_E_READER_UNSUPPORTED = -2146435046;
        public const int SCARD_E_DUPLICATE_READER = -2146435045;
        public const int SCARD_E_CARD_UNSUPPORTED = -2146435044;
        public const int SCARD_E_NO_SERVICE = -2146435043;
        public const int SCARD_E_SERVICE_STOPPED = -2146435042;

        public const int SCARD_W_UNSUPPORTED_CARD = -2146435041;
        public const int SCARD_W_UNRESPONSIVE_CARD = -2146435040;
        public const int SCARD_W_UNPOWERED_CARD = -2146435039;
        public const int SCARD_W_RESET_CARD = -2146435038;
        public const int SCARD_W_REMOVED_CARD = -2146435037;

        /*===========================================================
        '   PROTOCOL
        '===========================================================*/
        public const int SCARD_PROTOCOL_UNDEFINED = 0x00;          // There is no active protocol.
        public const int SCARD_PROTOCOL_T0 = 0x01;                 // T=0 is the active protocol.
        public const int SCARD_PROTOCOL_T1 = 0x02;                 // T=1 is the active protocol.
        public const int SCARD_PROTOCOL_RAW = 0x10000;             // Raw is the active protocol.
                                                                   //public const int SCARD_PROTOCOL_DEFAULT = 0x80000000;      // Use implicit PTS.
        /*===========================================================
        '   READER STATE
        '===========================================================*/
        public const int SCARD_UNKNOWN = 0;
        /*===============================================================
        ' This value implies the driver is unaware of the current 
        ' state of the reader.
        '===============================================================*/
        public const int SCARD_ABSENT = 1;
        /*===============================================================
        ' This value implies there is no card in the reader.
        '===============================================================*/
        public const int SCARD_PRESENT = 2;
        /*===============================================================
        ' This value implies there is a card is present in the reader, 
        'but that it has not been moved into position for use.
        '===============================================================*/
        public const int SCARD_SWALLOWED = 3;
        /*===============================================================
        ' This value implies there is a card in the reader in position 
        ' for use.  The card is not powered.
        '===============================================================*/
        public const int SCARD_POWERED = 4;
        /*===============================================================
        ' This value implies there is power is being provided to the card, 
        ' but the Reader Driver is unaware of the mode of the card.
        '===============================================================*/
        public const int SCARD_NEGOTIABLE = 5;
        /*===============================================================
        ' This value implies the card has been reset and is awaiting 
        ' PTS negotiation.
        '===============================================================*/
        public const int SCARD_SPECIFIC = 6;
        /*===============================================================
        ' This value implies the card has been reset and specific 
        ' communication protocols have been established.
        '===============================================================*/

        /*==========================================================================
        ' Prototypes
        '==========================================================================*/


        [DllImport("winscard.dll")]
        public static extern int SCardEstablishContext(int dwScope, int pvReserved1, int pvReserved2, ref int phContext);

        [DllImport("winscard.dll")]
        public static extern int SCardReleaseContext(int phContext);

        [DllImport("winscard.dll")]
        public static extern int SCardConnect(int hContext, string szReaderName, int dwShareMode, int dwPrefProtocol, ref int phCard, ref int ActiveProtocol);

        [DllImport("winscard.dll")]
        public static extern int SCardBeginTransaction(int hCard);

        [DllImport("winscard.dll")]
        public static extern int SCardDisconnect(int hCard, int Disposition);

        [DllImport("winscard.dll")]
        public static extern int SCardListReaderGroups(int hContext, ref string mzGroups, ref int pcchGroups);

        [DllImport("winscard.DLL", EntryPoint = "SCardListReadersA", CharSet = CharSet.Ansi)]
        public static extern int SCardListReaders(
            int hContext,
            byte[] Groups,
            byte[] Readers,
            ref int pcchReaders
            );

        /// <summary>
        /// The SCardStatus function provides the current status of a smart card in a reader. You can call it any time after a successful call to SCardConnect and before a successful call to SCardDisconnect. It does not affect the state of the reader or reader driver.
        /// http://msdn.microsoft.com/en-us/library/windows/desktop/aa379803(v=vs.85).aspx
        /// </summary>
        /// <param name="hCard"></param>
        /// <param name="szReaderName"></param>
        /// <param name="pcchReaderLen"></param>
        /// <param name="State"></param>
        /// <param name="Protocol"></param>
        /// <param name="ATR"></param>
        /// <param name="ATRLen"></param>
        /// <returns></returns>
        [DllImport("winscard.dll")]
        public static extern int SCardStatus(int hCard, string szReaderName, ref int pcchReaderLen, ref int State, ref int Protocol, ref byte ATR, ref int ATRLen);

        [DllImport("winscard.dll")]
        public static extern int SCardEndTransaction(int hCard, int Disposition);

        [DllImport("winscard.dll")]
        public static extern int SCardState(int hCard, ref uint State, ref uint Protocol, ref byte ATR, ref uint ATRLen);

        [DllImport("winscard.dll")]
        public static extern int SCardTransmit(int hCard, ref ScardIoRequest pioSendRequest, ref byte SendBuff, int SendBuffLen, ref ScardIoRequest pioRecvRequest, ref byte RecvBuff, ref int RecvBuffLen);

        private const string ScardECancelledMessage = "The action was canceled by an SCardCancel request.";
        private const string ScardECantDisposeMessage = "The system could not dispose of the media in the requested manner.";
        private const string ScardECardUnsupportedMessage = "The smart card does not meet minimal requirements for support.";
        private const string ScardEDuplicateReaderMessage = "The reader driver didn't produce a unique reader name.";
        private const string ScardEInsufficientBufferMessage = "The data buffer for returned data is too small for the returned data.";
        private const string ScardEInvalidAtrMessage = "An ATR string obtained from the registry is not a valid ATR string.";
        private const string ScardEInvalidHandleMessage = "The supplied handle was invalid.";
        private const string ScardEInvalidParameterMessage = "One or more of the supplied parameters could not be properly interpreted.";
        private const string ScardEInvalidTargetMessage = "Registry startup information is missing or invalid.";
        private const string ScardEInvalidValueMessage = "One or more of the supplied parameter values could not be properly interpreted.";
        private const string ScardENotReadyMessage = "The reader or card is not ready to accept commands.";
        private const string ScardENotTransactedMessage = "An attempt was made to end a non-existent transaction.";
        private const string ScardENoMemoryMessage = "Not enough memory available to complete this command.";
        private const string ScardENoServiceMessage = "The smart card resource manager is not running.";
        private const string ScardENoSmartcardMessage = "The operation requires a smart card, but no smart card is currently in the device.";
        private const string ScardEPciTooSmallMessage = "The PCI receive buffer was too small.";
        private const string ScardEProtoMismatchMessage = "The requested protocols are incompatible with the protocol currently in use with the card.";
        private const string ScardEReaderUnavailableMessage = "The specified reader is not currently available for use.";
        private const string ScardEReaderUnsupportedMessage = "The reader driver does not meet minimal requirements for support.";
        private const string ScardEServiceStoppedMessage = "The smart card resource manager has shut down.";
        private const string ScardESharingViolationMessage = "The smart card cannot be accessed because of other outstanding connections.";
        private const string ScardESystemCancelledMessage = "The action was canceled by the system, presumably to log off or shut down.";
        private const string ScardETimeoutMessage = "The user-specified timeout value has expired.";
        private const string ScardEUnknownCardMessage = "The specified smart card name is not recognized.";
        private const string ScardEUnknownReaderMessage = "The specified reader name is not recognized.";
        private const string ScardFCommErrorMessage = "An internal communications error has been detected.";
        private const string ScardFInternalErrorMessage = "An internal consistency check failed.";
        private const string ScardFUnknownErrorMessage = "An internal error has been detected, but the source is unknown.";
        private const string ScardFWaitedTooLongMessage = "An internal consistency timer has expired.";
        private const string ScardSuccessMessage = "No error was encountered.";
        private const string ScardWRemovedCardMessage = "The smart card has been removed, so that further communication is not possible.";
        private const string ScardWResetCardMessage = "The smart card has been reset, so any shared state information is invalid.";
        private const string ScardWUnpoweredCardMessage = "Power has been removed from the smart card, so that further communication is not possible.";
        private const string ScardWUnresponsiveCardMessage = "The smart card is not responding to a reset.";
        private const string ScardWUnsupportedCardMessage = "The reader cannot communicate with the card, due to ATR string configuration conflicts.";
        private const string DefaultMessage = "UnKnown Error.";


        public static string GetScardErrMsg(int ReturnCode)
        {
            switch (ReturnCode)
            {
                case SCARD_E_CANCELLED:
                    return (ScardECancelledMessage);
                case SCARD_E_CANT_DISPOSE:
                    return (ScardECantDisposeMessage);
                case SCARD_E_CARD_UNSUPPORTED:
                    return (ScardECardUnsupportedMessage);
                case SCARD_E_DUPLICATE_READER:
                    return (ScardEDuplicateReaderMessage);
                case SCARD_E_INSUFFICIENT_BUFFER:
                    return (ScardEInsufficientBufferMessage);
                case SCARD_E_INVALID_ATR:
                    return (ScardEInvalidAtrMessage);
                case SCARD_E_INVALID_HANDLE:
                    return (ScardEInvalidHandleMessage);
                case SCARD_E_INVALID_PARAMETER:
                    return (ScardEInvalidParameterMessage);
                case SCARD_E_INVALID_TARGET:
                    return (ScardEInvalidTargetMessage);
                case SCARD_E_INVALID_VALUE:
                    return (ScardEInvalidValueMessage);
                case SCARD_E_NOT_READY:
                    return (ScardENotReadyMessage);
                case SCARD_E_NOT_TRANSACTED:
                    return (ScardENotTransactedMessage);
                case SCARD_E_NO_MEMORY:
                    return (ScardENoMemoryMessage);
                case SCARD_E_NO_SERVICE:
                    return (ScardENoServiceMessage);
                case SCARD_E_NO_SMARTCARD:
                    return (ScardENoSmartcardMessage);
                case SCARD_E_PCI_TOO_SMALL:
                    return (ScardEPciTooSmallMessage);
                case SCARD_E_PROTO_MISMATCH:
                    return (ScardEProtoMismatchMessage);
                case SCARD_E_READER_UNAVAILABLE:
                    return (ScardEReaderUnavailableMessage);
                case SCARD_E_READER_UNSUPPORTED:
                    return (ScardEReaderUnsupportedMessage);
                case SCARD_E_SERVICE_STOPPED:
                    return (ScardEServiceStoppedMessage);
                case SCARD_E_SHARING_VIOLATION:
                    return (ScardESharingViolationMessage);
                case SCARD_E_SYSTEM_CANCELLED:
                    return (ScardESystemCancelledMessage);
                case SCARD_E_TIMEOUT:
                    return (ScardETimeoutMessage);
                case SCARD_E_UNKNOWN_CARD:
                    return (ScardEUnknownCardMessage);
                case SCARD_E_UNKNOWN_READER:
                    return (ScardEUnknownReaderMessage);
                case SCARD_F_COMM_ERROR:
                    return (ScardFCommErrorMessage);
                case SCARD_F_INTERNAL_ERROR:
                    return (ScardFInternalErrorMessage);
                case SCARD_F_UNKNOWN_ERROR:
                    return (ScardFUnknownErrorMessage);
                case SCARD_F_WAITED_TOO_LONG:
                    return (ScardFWaitedTooLongMessage);
                case ScardSuccess:
                    return (ScardSuccessMessage);
                case SCARD_W_REMOVED_CARD:
                    return (ScardWRemovedCardMessage);
                case SCARD_W_RESET_CARD:
                    return (ScardWResetCardMessage);
                case SCARD_W_UNPOWERED_CARD:
                    return (ScardWUnpoweredCardMessage);
                case SCARD_W_UNRESPONSIVE_CARD:
                    return (ScardWUnresponsiveCardMessage);
                case SCARD_W_UNSUPPORTED_CARD:
                    return (ScardWUnsupportedCardMessage);
                default:
                    return (DefaultMessage);
            }
        }

        public WinsCardWrapper()
        {
            //
            // TODO: Add constructor logic here
            //
        }


    }
}

标签: c#nfcsmartcard.net-5

解决方案


推荐阅读