自宅サーバの整理箱

自宅サーバを構築しwordpress,fedora,CentOSの作業メモ

*

VB.netでPC/SC(NFC通信)してFelicaやMifareを読み取るサンプル

      2016/09/19

仕事でパソリRC-S380フェリカリーダを使用してIDmを読み取る必要があったので急いで徹夜して作りました。VB.netでのサンプルソースとして公開します。

pc/sc pasori

(2015.11.12 更新)
ソースファイルをダウンロードできるようにしました。
中央あたりにリンクあります。
 
(2015.3.14 更新)
誤記ありましたので見直しました。
  

パソリRC-S380でフェリカを読む

このラッパークラスを使えばTypeA(Mifare), TypeB, FeliCa の ID を読み取ることが出来ます。VB.netでの実装ノウハウがネット上に少なく苦労しましたので、メモ書きとしてここに残したいと思います。

私の実装・開発環境

◆OS:windows7(32bit)
◆リーダ:PaSoRi RC-S380
◆Visual Studio 2010 express
◆.Net Framework 3.5
◆開発キッドは使いません「WinSCard.dll」を使います。Windows7以降はOSに入ってます

開発・評価用の無償版SDKがSonyから提供されますが、独自処理であるため、今後の国際規格であるPC/SCで実装したいと思います。

メイン処理のサンプルコード

1、メイン処理はこんな感じで作ります。スレッド化するといいと思います
  フォームやボタンなどは適当にで作ってください。
(2015.3.14 更新しました)

'ICカードリードオブジェクト生成
dim pcsc As clsWinSCard
dim IDm  As String '取得したIDmを格納する

pcsc = new clsWinSCard

While True
 Select Case pcsc.mState
 Case 0
	'0) サービスの確認
	pcsc.SCardEstablishContext()

 Case 1
	'1) カードリーダーの確認
	pcsc.SCardListReaders()

 Case 2
	'2) 状態遷移
	'If pcsc.SCardGetStatusChange() = 0 Then
	'	'OK
	'Else
	'	'ポーリング再開
	'	continue
	'End If
	'カード補足の遷移状態はやめました
	pcsc.mState = 3

 Case 3
	'3) カードの確認
	pcsc.SCardConnect()

 Case 4
	'4) カードとの通信
	pcsc.SCardTransmit()

 Case 5
	'5) カードの解放
	pcsc.SCardDisconnect()
	pcsc.mState = 2
	'カード番号の表示
	IDm = pcsc.mCardNo
 End Select
end While

ラッパークラスを実装するサンプルコード

2、次にラッパークラスを実装しますのでコピペしてください。
(2015.3.14 更新しました)
■clsWinSCardWrapper.vb

'
'-----------------------------------------------------------
' All Rights Reserved , Copyright (C) 2014
'-----------------------------------------------------------

Imports System
Imports System.Text
Imports System.Linq
Imports System.Runtime.InteropServices

Public Class WinSCardWrapper

    Public Const SCARD_S_SUCCESS As Integer = 0
    Public Const SCARD_F_INTERNAL_ERROR As Integer = &H80100001
    Public Const SCARD_E_CANCELLED As Integer = &H80100002
    Public Const SCARD_E_INVALID_HANDLE As Integer = &H80100003
    Public Const SCARD_E_INVALID_PARAMETER As Integer = &H80100004
    Public Const SCARD_E_INVALID_TARGET As Integer = &H80100005
    Public Const SCARD_E_NO_MEMORY As Integer = &H80100006
    Public Const SCARD_F_WAITED_TOO_LONG As Integer = &H80100007
    Public Const SCARD_E_INSUFFICIENT_BUFFER As Integer = &H80100008
    Public Const SCARD_E_UNKNOWN_READER As Integer = &H80100009
    Public Const SCARD_E_TIMEOUT As Integer = &H8010000A
    Public Const SCARD_E_SHARING_VIOLATION As Integer = &H8010000B
    Public Const SCARD_E_NO_SMARTCARD As Integer = &H8010000C
    Public Const SCARD_E_UNKNOWN_CARD As Integer = &H8010000D
    Public Const SCARD_E_CANT_DISPOSE As Integer = &H8010000E
    Public Const SCARD_E_PROTO_MISMATCH As Integer = &H8010000F
    Public Const SCARD_E_NOT_READY As Integer = &H80100010
    Public Const SCARD_E_INVALID_VALUE As Integer = &H80100011
    Public Const SCARD_E_SYSTEM_CANCELLED As Integer = &H80100012
    Public Const SCARD_E_COMM_ERROR As Integer = &H80100013
    Public Const SCARD_F_UNKNOWN_ERROR As Integer = &H80100014
    Public Const SCARD_E_INVALID_ATR As Integer = &H80100015
    Public Const SCARD_E_NOT_TRANSACTED As Integer = &H80100016
    Public Const SCARD_E_READER_UNAVAILABLE As Integer = &H80100017
    Public Const SCARD_P_SHUTDOWN As Integer = &H80100018
    Public Const SCARD_E_PCI_TOO_SMALL As Integer = &H80100019
    Public Const SCARD_E_READER_UNSUPPORTED As Integer = &H8010001A
    Public Const SCARD_E_DUPLICATE_READER As Integer = &H8010001B
    Public Const SCARD_E_CARD_UNSUPPORTED As Integer = &H8010001C
    Public Const SCARD_E_NO_SERVICE As Integer = &H8010001D
    Public Const SCARD_E_SERVICE_STOPPED As Integer = &H8010001E
    Public Const SCARD_E_UNEXPECTED As Integer = &H8010001F
    Public Const SCARD_E_ICC_INSTALLATION As Integer = &H80100020
    Public Const SCARD_E_ICC_CREATEORDER As Integer = &H80100021
    Public Const SCARD_E_UNSUPPORTED_FEATURE As Integer = &H80100022
    Public Const SCARD_E_DIR_NOT_FOUND As Integer = &H80100023
    Public Const SCARD_E_FILE_NOT_FOUND As Integer = &H80100024
    Public Const SCARD_E_NO_DIR As Integer = &H80100025
    Public Const SCARD_E_NO_FILE As Integer = &H80100026
    Public Const SCARD_E_NO_ACCESS As Integer = &H80100027
    Public Const SCARD_E_WRITE_TOO_MANY As Integer = &H80100028
    Public Const SCARD_E_BAD_SEEK As Integer = &H80100029
    Public Const SCARD_E_INVALID_CHV As Integer = &H8010002A
    Public Const SCARD_E_UNKNOWN_RES_MNG As Integer = &H8010002B
    Public Const SCARD_E_NO_SUCH_CERTIFICATE As Integer = &H8010002C
    Public Const SCARD_E_CERTIFICATE_UNAVAILABLE As Integer = &H8010002D
    Public Const SCARD_E_NO_READERS_AVAILABLE As Integer = &H8010002E
    Public Const SCARD_E_COMM_DATA_LOST As Integer = &H8010002F
    Public Const SCARD_E_NO_KEY_CONTAINER As Integer = &H80100030
    Public Const SCARD_E_SERVER_TOO_BUSY As Integer = &H80100031
    Public Const SCARD_E_PIN_CACHE_EXPIRED As Integer = &H80100032
    Public Const SCARD_E_NO_PIN_CACHE As Integer = &H80100033
    Public Const SCARD_E_READ_ONLY_CARD As Integer = &H80100034
    Public Const SCARD_W_UNSUPPORTED_CARD As Integer = &H80100065
    Public Const SCARD_W_UNRESPONSIVE_CARD As Integer = &H80100066
    Public Const SCARD_W_UNPOWERED_CARD As Integer = &H80100067
    Public Const SCARD_W_RESET_CARD As Integer = &H80100068
    Public Const SCARD_W_REMOVED_CARD As Integer = &H80100069
    Public Const SCARD_W_SECURITY_VIOLATION As Integer = &H8010006A
    Public Const SCARD_W_WRONG_CHV As Integer = &H8010006B
    Public Const SCARD_W_CHV_BLOCKED As Integer = &H8010006C
    Public Const SCARD_W_EOF As Integer = &H8010006D
    Public Const SCARD_W_CANCELLED_BY_USER As Integer = &H8010006E
    Public Const SCARD_W_CARD_NOT_AUTHENTICATED As Integer = &H8010006F
    Public Const SCARD_W_CACHE_ITEM_NOT_FOUND As Integer = &H80100070
    Public Const SCARD_W_CACHE_ITEM_STALE As Integer = &H80100071
    Public Const SCARD_W_CACHE_ITEM_TOO_BIG As Integer = &H80100072
    Public Const SCARD_PROTOCOL_T0 As Integer = 1
    Public Const SCARD_PROTOCOL_T1 As Integer = 2
    Public Const SCARD_PROTOCOL_RAW As Integer = 4
    Public Const SCARD_SCOPE_USER As UInteger = 0
    Public Const SCARD_SCOPE_TERMINAL As UInteger = 1
    Public Const SCARD_SCOPE_SYSTEM As UInteger = 2
    Public Const SCARD_STATE_UNAWARE As Integer = &H0
    Public Const SCARD_STATE_IGNORE As Integer = &H1
    Public Const SCARD_STATE_CHANGED As Integer = &H2
    Public Const SCARD_STATE_UNKNOWN As Integer = &H4
    Public Const SCARD_STATE_UNAVAILABLE As Integer = &H8
    Public Const SCARD_STATE_EMPTY As Integer = &H10
    Public Const SCARD_STATE_PRESENT As Integer = &H20
    Public Const SCARD_STATE_AIRMATCH As Integer = &H40
    Public Const SCARD_STATE_EXCLUSIVE As Integer = &H80
    Public Const SCARD_STATE_INUSE As Integer = &H100
    Public Const SCARD_STATE_MUTE As Integer = &H200
    Public Const SCARD_STATE_UNPOWERED As Integer = &H400
    Public Const SCARD_SHARE_EXCLUSIVE As Integer = &H1
    Public Const SCARD_SHARE_SHARED As Integer = &H2
    Public Const SCARD_SHARE_DIRECT As Integer = &H3
    Public Const SCARD_LEAVE_CARD As Integer = 0
    Public Const SCARD_RESET_CARD As Integer = 1
    Public Const SCARD_UNPOWER_CARD As Integer = 2
    Public Const SCARD_EJECT_CARD As Integer = 3


     _
    Public Shared Function SCardEstablishContext(ByVal dwScope As UInteger, ByVal pvReserved1 As IntPtr, ByVal pvReserved2 As IntPtr, ByRef phContext As IntPtr) As UInteger
    End Function

     _
    Public Shared Function SCardListReaders(ByVal hContext As IntPtr, ByVal mszGroups As Byte(), ByVal mszReaders As Byte(), ByRef pcchReaders As UInt32) As UInteger
    End Function

     _
    Public Shared Function SCardReleaseContext(ByVal phContext As IntPtr) As UInteger
    End Function

     _
    Public Shared Function SCardConnect(ByVal hContext As IntPtr, ByVal szReader As String, ByVal dwShareMode As UInteger, ByVal dwPreferredProtocols As UInteger, ByRef phCard As IntPtr, ByRef pdwActiveProtocol As IntPtr) As UInteger
    End Function

     _
    Public Shared Function SCardDisconnect(ByVal hCard As IntPtr, ByVal Disposition As Integer) As UInteger
    End Function

    Public Class SCARD_IO_REQUEST
        Friend dwProtocol As UInteger
        Friend cbPciLength As Integer
        Public Sub New()
            dwProtocol = 0
        End Sub
    End Class

     _
    Public Shared Function SCardStatus(ByVal hCard As IntPtr, ByVal szReaderName As String, ByVal SendBuff As Byte(), ByVal SendBuffLen As Integer, ByVal pioRecvRequest As SCARD_IO_REQUEST, ByVal RecvBuff As Byte(), ByRef RecvBuffLen As Integer) As UInteger
    End Function

     _
    Public Shared Function SCardTransmit(ByVal hCard As IntPtr, ByVal pioSendRequest As IntPtr, ByVal SendBuff As Byte(), ByVal SendBuffLen As Integer, ByVal pioRecvRequest As SCARD_IO_REQUEST, ByVal RecvBuff As Byte(), ByRef RecvBuffLen As Integer) As UInteger
    End Function

     _
    Public Shared Function SCardControl(ByVal hCard As IntPtr, ByVal controlCode As Integer, ByVal inBuffer As Byte(), ByVal inBufferLen As Integer, ByVal outBuffer As Byte(), ByVal outBufferLen As Integer, ByRef bytesReturned As Integer) As UInteger
    End Function


    Public Structure SCARD_READERSTATE
        Friend szReader As String
        Friend pvUserData As IntPtr
        Friend dwCurrentState As UInt32
        Friend dwEventState As UInt32
        Friend cbAtr As UInt32

        Friend rgbAtr As Byte()
    End Structure

     _
    Public Shared Function SCardGetStatusChange(ByVal hContext As IntPtr, ByVal dwTimeout As Integer,  ByVal rgReaderStates As SCARD_READERSTATE, ByVal cReaders As Integer) As UInteger
    End Function

     _
    Public Shared Function SCardFreeMemory(ByVal hContext As IntPtr, ByVal szReader As String) As UInteger
    End Function

     _
    Public Shared Function LoadLibrary(ByVal lpFileName As String) As IntPtr
    End Function

     _
    Public Shared Sub FreeLibrary(ByVal handle As IntPtr)
    End Sub

     _
    Public Shared Function GetProcAddress(ByVal handle As IntPtr, ByVal procName As String) As IntPtr
    End Function

    Public Shared Function GetErrorMessage(ByVal errNo As UInteger) As String

        Dim strMessage As String = vbNullString

        Select Case errNo
            Case WinSCardWrapper.GetUInteger(SCARD_F_INTERNAL_ERROR)
                strMessage = errNo.ToString + " INTERNAL ERROR"
            Case WinSCardWrapper.GetUInteger(SCARD_E_CANCELLED)
                strMessage = errNo.ToString + " CANCELLED"
            Case WinSCardWrapper.GetUInteger(SCARD_E_INVALID_HANDLE)
                strMessage = errNo.ToString + " INVALID HANDLE"
            Case WinSCardWrapper.GetUInteger(SCARD_E_INVALID_PARAMETER)
                strMessage = errNo.ToString + " INVALID PARAMETER"
            Case WinSCardWrapper.GetUInteger(SCARD_E_INVALID_TARGET)
                strMessage = errNo.ToString + " INVALID TARGET"
            Case WinSCardWrapper.GetUInteger(SCARD_E_NO_MEMORY)
                strMessage = errNo.ToString + " NO MEMORY"
            Case WinSCardWrapper.GetUInteger(SCARD_F_WAITED_TOO_LONG)
                strMessage = errNo.ToString + " WAITED TOO LONG"
            Case WinSCardWrapper.GetUInteger(SCARD_E_INSUFFICIENT_BUFFER)
                strMessage = errNo.ToString + " INSUFFICIENT BUFFER"
            Case WinSCardWrapper.GetUInteger(SCARD_E_UNKNOWN_READER)
                strMessage = errNo.ToString + " UNKNOWN READER"
            Case WinSCardWrapper.GetUInteger(SCARD_E_TIMEOUT)
                strMessage = errNo.ToString + " TIMEOUT"
            Case WinSCardWrapper.GetUInteger(SCARD_E_SHARING_VIOLATION)
                strMessage = errNo.ToString + " SHARING VIOLATION"
            Case WinSCardWrapper.GetUInteger(SCARD_E_NO_SMARTCARD)
                strMessage = errNo.ToString + " NO SMARTCARD"
            Case WinSCardWrapper.GetUInteger(SCARD_E_UNKNOWN_CARD)
                strMessage = errNo.ToString + " UNKNOWN CARD"
            Case WinSCardWrapper.GetUInteger(SCARD_E_CANT_DISPOSE)
                strMessage = errNo.ToString + " CANT DISPOSE"
            Case WinSCardWrapper.GetUInteger(SCARD_E_PROTO_MISMATCH)
                strMessage = errNo.ToString + " PROTO MISMATCH"
            Case WinSCardWrapper.GetUInteger(SCARD_E_NOT_READY)
                strMessage = errNo.ToString + " NOT READY"
            Case WinSCardWrapper.GetUInteger(SCARD_E_INVALID_VALUE)
                strMessage = errNo.ToString + " INVALID VALUE"
            Case WinSCardWrapper.GetUInteger(SCARD_E_SYSTEM_CANCELLED)
                strMessage = errNo.ToString + " SYSTEM CANCELLED"
            Case WinSCardWrapper.GetUInteger(SCARD_E_COMM_ERROR)
                strMessage = errNo.ToString + " COMM ERROR"
            Case WinSCardWrapper.GetUInteger(SCARD_F_UNKNOWN_ERROR)
                strMessage = errNo.ToString + " UNKNOWN ERROR"
            Case WinSCardWrapper.GetUInteger(SCARD_E_INVALID_ATR)
                strMessage = errNo.ToString + " INVALID ATR"
            Case WinSCardWrapper.GetUInteger(SCARD_E_NOT_TRANSACTED)
                strMessage = errNo.ToString + " NOT TRANSACTED"
            Case WinSCardWrapper.GetUInteger(SCARD_E_READER_UNAVAILABLE)
                strMessage = errNo.ToString + " READER UNAVAILABLE"
            Case WinSCardWrapper.GetUInteger(SCARD_P_SHUTDOWN)
                strMessage = errNo.ToString + " SHUTDOWN"
            Case WinSCardWrapper.GetUInteger(SCARD_E_PCI_TOO_SMALL)
                strMessage = errNo.ToString + " PCI TOO SMALL"
            Case WinSCardWrapper.GetUInteger(SCARD_E_READER_UNSUPPORTED)
                strMessage = errNo.ToString + " READER UNSUPPORTED"
            Case WinSCardWrapper.GetUInteger(SCARD_E_DUPLICATE_READER)
                strMessage = errNo.ToString + " DUPLICATE READER"
            Case WinSCardWrapper.GetUInteger(SCARD_E_CARD_UNSUPPORTED)
                strMessage = errNo.ToString + " CARD UNSUPPORTED"
            Case WinSCardWrapper.GetUInteger(SCARD_E_NO_SERVICE)
                strMessage = errNo.ToString + " NO SERVICE"
            Case WinSCardWrapper.GetUInteger(SCARD_E_SERVICE_STOPPED)
                strMessage = errNo.ToString + " SERVICE STOPPED"
            Case WinSCardWrapper.GetUInteger(SCARD_E_UNEXPECTED)
                strMessage = errNo.ToString + " UNEXPECTED"
            Case WinSCardWrapper.GetUInteger(SCARD_E_ICC_INSTALLATION)
                strMessage = errNo.ToString + " ICC INSTALLATION"
            Case WinSCardWrapper.GetUInteger(SCARD_E_ICC_CREATEORDER)
                strMessage = errNo.ToString + " ICC CREATEORDER"
            Case WinSCardWrapper.GetUInteger(SCARD_E_UNSUPPORTED_FEATURE)
                strMessage = errNo.ToString + " UNSUPPORTED FEATURE"
            Case WinSCardWrapper.GetUInteger(SCARD_E_DIR_NOT_FOUND)
                strMessage = errNo.ToString + " DIR NOT FOUND"
            Case WinSCardWrapper.GetUInteger(SCARD_E_FILE_NOT_FOUND)
                strMessage = errNo.ToString + " FILE NOT FOUND"
            Case WinSCardWrapper.GetUInteger(SCARD_E_NO_DIR)
                strMessage = errNo.ToString + " NO DIR"
            Case WinSCardWrapper.GetUInteger(SCARD_E_NO_FILE)
                strMessage = errNo.ToString + " NO FILE"
            Case WinSCardWrapper.GetUInteger(SCARD_E_NO_ACCESS)
                strMessage = errNo.ToString + " NO ACCESS"
            Case WinSCardWrapper.GetUInteger(SCARD_E_WRITE_TOO_MANY)
                strMessage = errNo.ToString + " WRITE TOO MANY"
            Case WinSCardWrapper.GetUInteger(SCARD_E_BAD_SEEK)
                strMessage = errNo.ToString + " BAD SEEK"
            Case WinSCardWrapper.GetUInteger(SCARD_E_INVALID_CHV)
                strMessage = errNo.ToString + " INVALID CHV"
            Case WinSCardWrapper.GetUInteger(SCARD_E_UNKNOWN_RES_MNG)
                strMessage = errNo.ToString + " UNKNOWN RES MNG"
            Case WinSCardWrapper.GetUInteger(SCARD_E_NO_SUCH_CERTIFICATE)
                strMessage = errNo.ToString + " NO SUCH CERTIFICATE"
            Case WinSCardWrapper.GetUInteger(SCARD_E_CERTIFICATE_UNAVAILABLE)
                strMessage = errNo.ToString + " CERTIFICATE UNAVAILABLE"
            Case WinSCardWrapper.GetUInteger(SCARD_E_NO_READERS_AVAILABLE)
                strMessage = errNo.ToString + " NO READERS AVAILABLE"
            Case WinSCardWrapper.GetUInteger(SCARD_E_COMM_DATA_LOST)
                strMessage = errNo.ToString + " COMM DATA LOST"
            Case WinSCardWrapper.GetUInteger(SCARD_E_NO_KEY_CONTAINER)
                strMessage = errNo.ToString + " NO KEY CONTAINER"
            Case WinSCardWrapper.GetUInteger(SCARD_E_SERVER_TOO_BUSY)
                strMessage = errNo.ToString + " SERVER TOO BUSY"
            Case WinSCardWrapper.GetUInteger(SCARD_E_PIN_CACHE_EXPIRED)
                strMessage = errNo.ToString + " PIN CACHE EXPIRED"
            Case WinSCardWrapper.GetUInteger(SCARD_E_NO_PIN_CACHE)
                strMessage = errNo.ToString + " NO PIN CACHE"
            Case WinSCardWrapper.GetUInteger(SCARD_E_READ_ONLY_CARD)
                strMessage = errNo.ToString + " READ ONLY CARD"
            Case WinSCardWrapper.GetUInteger(SCARD_W_UNSUPPORTED_CARD)
                strMessage = errNo.ToString + " UNSUPPORTED CARD"
            Case WinSCardWrapper.GetUInteger(SCARD_W_UNRESPONSIVE_CARD)
                strMessage = errNo.ToString + " UNRESPONSIVE CARD"
            Case WinSCardWrapper.GetUInteger(SCARD_W_UNPOWERED_CARD)
                strMessage = errNo.ToString + " UNPOWERED CARD"
            Case WinSCardWrapper.GetUInteger(SCARD_W_RESET_CARD)
                strMessage = errNo.ToString + " RESET CARD"
            Case WinSCardWrapper.GetUInteger(SCARD_W_REMOVED_CARD)
                strMessage = errNo.ToString + " REMOVED CARD"
            Case WinSCardWrapper.GetUInteger(SCARD_W_SECURITY_VIOLATION)
                strMessage = errNo.ToString + " SECURITY VIOLATION"
            Case WinSCardWrapper.GetUInteger(SCARD_W_WRONG_CHV)
                strMessage = errNo.ToString + " WRONG CHV"
            Case WinSCardWrapper.GetUInteger(SCARD_W_CHV_BLOCKED)
                strMessage = errNo.ToString + " CHV BLOCKED"
            Case WinSCardWrapper.GetUInteger(SCARD_W_EOF)
                strMessage = errNo.ToString + " EOF"
            Case WinSCardWrapper.GetUInteger(SCARD_W_CANCELLED_BY_USER)
                strMessage = errNo.ToString + " CANCELLED BY USER"
            Case WinSCardWrapper.GetUInteger(SCARD_W_CARD_NOT_AUTHENTICATED)
                strMessage = errNo.ToString + " CARD NOT AUTHENTICATED"
            Case WinSCardWrapper.GetUInteger(SCARD_W_CACHE_ITEM_NOT_FOUND)
                strMessage = errNo.ToString + " CACHE ITEM NOT FOUND"
            Case WinSCardWrapper.GetUInteger(SCARD_W_CACHE_ITEM_STALE)
                strMessage = errNo.ToString + " CACHE ITEM STALE"
            Case WinSCardWrapper.GetUInteger(SCARD_W_CACHE_ITEM_TOO_BIG)
                strMessage = errNo.ToString + " CACHE ITEM TOO BIG"
            Case Else
                strMessage = errNo.ToString + " OTHER ERROR"
        End Select
        Return strMessage
    End Function

    Public Shared Function GetUInteger(ByVal p_Value As Integer) As UInteger
        Return p_Value + 2 ^ 32
    End Function
End Class

ラッパークラスを実装するサンプルコード2

3、最後にメソッドになります。こんな感じに作りましたので
  これもコピペで使ってください。
(2015.3.14 更新しました)
■clsWinSCard.vb

'-----------------------------------------------------------
' All Rights Reserved , Copyright (C) 2014
'-----------------------------------------------------------

Imports System.Text

Public Class clsWinSCard

    Public mState As Integer
    Public mError As UInteger
    Public mErrMessage As String
    Public hContext As IntPtr
    Public mReader As String
    Public mSerialNumber As String
    Public hCard As IntPtr
    Public mCardNo As String
    Public mCardType As Integer     '0:Felica 1:Mifare
    Private intPolling As Integer = 500 'ICカードを読み込むポーリング間隔

    Private state As WinSCardWrapper.SCARD_READERSTATE = New WinSCardWrapper.SCARD_READERSTATE

    Public Sub New()
        mState = 0
        mError = 0
        mErrMessage = vbNullString
        hContext = IntPtr.Zero
        mReader = vbNullString
        mSerialNumber = vbNullString
        hCard = IntPtr.Zero
        mCardNo = String.Empty
        'state.dwCurrentState = WinSCardWrapper.SCARD_STATE_EMPTY
        state.dwCurrentState = WinSCardWrapper.SCARD_STATE_UNAWARE
    End Sub

    Public Sub SCardEstablishContext()

        '変数定義
        Dim URtn As UInteger = 0

        'SmartCardサービスの確認
        URtn = WinSCardWrapper.SCardEstablishContext(WinSCardWrapper.SCARD_SCOPE_USER, _
                                                     IntPtr.Zero, _
                                                     IntPtr.Zero, _
                                                     Me.hContext)
        If URtn <> WinSCardWrapper.SCARD_S_SUCCESS Then
            'エラー番号を記録
            Me.mState = URtn
            Me.mErrMessage = WinSCardWrapper.GetErrorMessage(Me.mError)
            'エラー内容をスロー
            Throw New Exception(Me.mErrMessage)
        End If

        '状態を0→1に遷移
        mState = 1

    End Sub

    Public Sub SCardListReaders()

        '変数定義
        Dim URtn As UInteger = 0
        Dim pcchReaders As UInteger = 0
        Dim mszReaders As Byte()

        '接続されているカードリーダーを確認
        'ここで取得できるカードリーダーの名前はNull文字で区切られた文字数
        URtn = WinSCardWrapper.SCardListReaders(Me.hContext, Nothing, Nothing, pcchReaders)
        If URtn <> WinSCardWrapper.SCARD_S_SUCCESS Then
            'エラー番号を記録
            Me.mError = URtn
            Me.mErrMessage = WinSCardWrapper.GetErrorMessage(Me.mError)
            'エラー内容をスロー
            Throw New Exception(Me.mErrMessage)
        End If

        '接続されているカードリーダの名前を取得
        'ここで取得できるカードリーダーの名前はNull文字で区切られたバイト配列(2バイト1文字)
        mszReaders = New Byte(Convert.ToInt32(pcchReaders) * 2 - 1) {}
        URtn = WinSCardWrapper.SCardListReaders(Me.hContext, Nothing, mszReaders, pcchReaders)
        If URtn <> WinSCardWrapper.SCARD_S_SUCCESS Then
            'エラー番号を記録
            Me.mError = URtn
            Me.mErrMessage = WinSCardWrapper.GetErrorMessage(Me.mError)
            'エラー内容をスロー
            Throw New Exception(Me.mErrMessage)
        End If

        Me.mReader = (New UnicodeEncoding).GetString(mszReaders)
        Me.mReader = Me.mReader.Substring(0, Me.mReader.IndexOf(vbNullChar))

        '状態を1→2に遷移
        Me.mState = 2

    End Sub


    Public Function SCardGetStatusChange() As Integer

        '変数定義
        Dim URtn As UInteger = 0

        state.szReader = Me.mReader

        'SmartCardステータス遷移
        URtn = WinSCardWrapper.SCardGetStatusChange(Me.hContext, -1, state, 1)
        If URtn <> WinSCardWrapper.SCARD_S_SUCCESS Then
            'エラー番号を記録
            Me.mState = URtn
            Me.mErrMessage = WinSCardWrapper.GetErrorMessage(Me.mError)
            'エラー内容をスロー
            Throw New Exception(Me.mErrMessage)
        End If

        '状態遷移
        If state.dwEventState = WinSCardWrapper.SCARD_STATE_PRESENT Then
            '状態を2→3に遷移
            mState = 3
            Return 0
        Else
            Return -1
        End If

    End Function

    Public Sub SCardConnect()

        '変数定義
        Dim URtn As UInteger = 0
        Dim pdwActiveProtocol As IntPtr = IntPtr.Zero

        'カードを確認
        URtn = WinSCardWrapper.SCardConnect(Me.hContext, _
                                            Me.mReader, _
                                            WinSCardWrapper.SCARD_SHARE_SHARED, _
                                            WinSCardWrapper.SCARD_PROTOCOL_T1, _
                                            Me.hCard, pdwActiveProtocol)
        If URtn = WinSCardWrapper.SCARD_S_SUCCESS Then
            '続行
        ElseIf URtn = WinSCardWrapper.GetUInteger(WinSCardWrapper.SCARD_W_REMOVED_CARD) Then
            'continue
            System.Threading.Thread.Sleep(intPolling)
            Exit Sub
        Else

            'エラー番号を記録
            Me.mError = URtn
            Me.mErrMessage = WinSCardWrapper.GetErrorMessage(Me.mError)
            'エラー内容をスロー
            Throw New Exception(Me.mErrMessage)
        End If

        '※以下のカードシリアル番号取得は別になくても構わない・・・たぶん

        Dim controlCode As Integer = &H3136B0
        Dim sendBuffer As Byte() = New Byte() {&HC0, &H8}
        Dim recvBuffer As Byte() = New Byte(64) {}
        Dim bytesReturned As Integer = 0

        'カードシリアル番号取得
        URtn = WinSCardWrapper.SCardControl( _
                    Me.hCard, controlCode, sendBuffer, _
                    sendBuffer.Length, _
                    recvBuffer, _
                    recvBuffer.Length, _
                    bytesReturned)
        If URtn <> WinSCardWrapper.SCARD_S_SUCCESS Then
            'エラー番号を記録
            Me.mError = URtn
            Me.mErrMessage = WinSCardWrapper.GetErrorMessage(Me.mError)
            'エラー内容をスロー
            Throw New Exception(Me.mErrMessage)
        End If

        Me.mSerialNumber = (New ASCIIEncoding).GetString(recvBuffer, 0, bytesReturned - 1)

        '状態を2→3に遷移
        mState = 4

    End Sub

    Public Sub SCardTransmit()

        '変数定義
        Dim URtn As UInteger = 0
        Dim sendBuffer As Byte() = New Byte() {&HFF, &HCA, &H0, &H0, &H0}    'Felica IDm取得コマンド
        'Dim sendBuffer As Byte() = New Byte() {&HFF, &HCA, &H0, &H0, &H4}   'Mifare UID取得コマンド
        Dim recvBuffer As Byte() = New Byte(511) {}
        Dim recvBufferLen As Integer = recvBuffer.Length
        Dim pioRecvRequest As WinSCardWrapper.SCARD_IO_REQUEST = New WinSCardWrapper.SCARD_IO_REQUEST()

        pioRecvRequest.cbPciLength = 255

        '動的にライブラリのポインタを取得・・・
        Dim hLoader As IntPtr = WinSCardWrapper.LoadLibrary("winscard.dll")
        Dim SCARD_PCI_T1 As IntPtr = WinSCardWrapper.GetProcAddress(hLoader, "g_rgSCardT1Pci")
        WinSCardWrapper.FreeLibrary(hLoader)

        pioRecvRequest = Nothing
        URtn = WinSCardWrapper.SCardTransmit(Me.hCard, SCARD_PCI_T1, sendBuffer, sendBuffer.Length, pioRecvRequest, recvBuffer, recvBufferLen)
        If URtn <> WinSCardWrapper.SCARD_S_SUCCESS Then
            'エラー番号を記録
            Me.mError = URtn
            Me.mErrMessage = WinSCardWrapper.GetErrorMessage(Me.mError)
            'エラー内容をスロー
            Throw New Exception(Me.mErrMessage)
        End If

        'Me.mCardNo = BitConverter.ToString(recvBuffer, 0, recvBufferLen - 2).Replace("-", "")
        Me.mCardNo = BitConverter.ToString(recvBuffer, 0, recvBufferLen - 2)

        '状態を3→4に遷移
        mState = 5

    End Sub

    Public Sub SCardDisconnect()

        '変数定義
        Dim URtn As UInteger = 0

        'カード解放
        URtn = WinSCardWrapper.SCardDisconnect(hCard, WinSCardWrapper.SCARD_LEAVE_CARD)
        If URtn <> WinSCardWrapper.SCARD_S_SUCCESS Then
            'カードの解放に失敗
        End If

    End Sub

    Public Sub SCardFreeMemory()

        '変数定義
        Dim URtn As UInteger = 0

        URtn = WinSCardWrapper.SCardFreeMemory(hContext, mReader)
        If URtn <> WinSCardWrapper.SCARD_S_SUCCESS Then
            'カードリーダーの解放に失敗
        End If

    End Sub

    Public Sub SCardReleaseContext()

        '変数定義
        Dim URtn As UInteger = 0

        URtn = WinSCardWrapper.SCardReleaseContext(hContext)
        If URtn <> WinSCardWrapper.SCARD_S_SUCCESS Then
            'カードリーダーの解放に失敗
        End If

    End Sub

End Class

 

使い方イメージとまとめ

‘0) PC/SCサービスの確認 SCardEstablishContext()
‘1) PaSoRiカードリーダーの確認 SCardListReaders()
‘2) ICカード補足の状態遷移 SCardGetStatusChange()
‘3) ICカードの確認 SCardConnect()
‘4) カードとの通信 SCardTransmit()
‘5) カードの解放 SCardDisconnect()

とCallすることで、カードへアクセスできると思います。
今回のサンプルではFelicaカードのIDmの取得と、MifareのIDmを取得するサンプルとなっています。このサンプルを使えばいろいろできると思います。
何かわからん事あればご質問お待ちしてます。(私も素人ですが)

修正差分の履歴

■修正差分の履歴です。
pcscの差分

diff2

diff3

diff4

diff5

 

サンプルソースとパソリ

■サンプルソースのダウンロードはこちらです。


 
■PaSoRi 安くなりましたよね。
1台家にあると意外と便利らしいです。確定申告もPCからできるとか。

 - PCSC, VB.net

 Total 9,713 views