Sample code for 30+ languages & platforms
AutoIt

PC/SC Wait for Smart Card Status Change (Inserted, Removed from Reader, etc.)

See more SCard Examples

Demonstrates how to synchronously wait for a status change, such as for a smart card to be inserted into a reader, or removed from a reader.

Note: This functionality was introduced in Chilkat v9.5.0.87.

Chilkat AutoIt Downloads

AutoIt
Local $bSuccess = False

; This example requires the Chilkat API to have been previously unlocked.
; See Global Unlock Sample for sample code.

$oScard = ObjCreate("Chilkat.SCard")

; First establish a context to the PC/SC Resource Manager
$bSuccess = $oScard.EstablishContext("user")
If ($bSuccess = False) Then
    ConsoleWrite($oScard.LastErrorText & @CRLF)
    Exit
EndIf

; First we'll examine the state of all connected readers to see which have smartcards already inserted..
; Get JSON containing information about the smartcards currently inserted into readers.
; This also includes information about USB security tokens.
$oJson = ObjCreate("Chilkat.JsonObject")
$bSuccess = $oScard.FindSmartcards($oJson)
If ($bSuccess = False) Then
    ConsoleWrite($oScard.LastErrorText & @CRLF)
    Exit
EndIf

; When writing this example, I have 3 smart card readers plugged into my system.
; One of them has a smart card inserted.
; Here's the JSON returned by FindSmartcards...

; {
;   "reader": [
;     {
;       "name": "Alcor Micro USB Smart Card Reader 0",
;       "state": "empty"
;     },
;     {
;       "name": "Generic Smart Card Reader Interface 0",
;       "state": "present",
;       "vendorName": "Generic",
;       "serialNumber": "3230303730383138303030303030303030",
;       "systemName": "Generic Smart Card Reader Interface 0",
;       "card": {
;         "atr": "3BFC180000813180459067464A00641606F2727E00E0",
;         "windows": {
;           "miniDriver": "tagliov70px.dll",
;           "cryptoProvider": "Microsoft Base Smart Card Crypto Provider",
;           "keyStorageProvider": "Microsoft Smart Card Key Storage Provider"
;         }
;       }
;     },
;     {
;       "name": "SCM Microsystems Inc. SCR33x USB Smart Card Reader 0",
;       "state": "empty"
;     }
;   ]
; }

$oJson.EmitCompact = False
ConsoleWrite($oJson.Emit() & @CRLF)
ConsoleWrite(" " & @CRLF)

; We can iterate over the JSON to find the readers with a smart card already inserted..
Local $sName
$oSbState = ObjCreate("Chilkat.StringBuilder")

Local $i = 0
Local $iCount_i = $oJson.SizeOfArray("reader")
While $i < $iCount_i
    $oJson.I = $i
    $sName = $oJson.StringOf("reader[i].name")

    $oSbState.Clear 
    $oJson.StringOfSb("reader[i].state",$oSbState)

    If ($oSbState.Contains("present",True) = True) Then
        ConsoleWrite($sName & " has a smart card inserted." & @CRLF)
    Else
        ConsoleWrite($sName & " does not have a smart card inserted." & @CRLF)
    EndIf

    $i = $i + 1
Wend
ConsoleWrite(" " & @CRLF)

; Now let's begin the code to wait for a change (where a smart card gets inserted or removed)

; Get the list of all readers.
$oStReaders = ObjCreate("Chilkat.StringTable")
$bSuccess = $oScard.ListReaders($oStReaders)
If ($bSuccess = False) Then
    ConsoleWrite($oScard.LastErrorText & @CRLF)
    Exit
EndIf

; Show the reader names..
Local $iNumReaders = $oStReaders.Count
$i = 0
While $i < $iNumReaders
    ConsoleWrite($i & ": " & $oStReaders.StringAt($i) & @CRLF)
    $i = $i + 1
Wend

; Sample output from the above loop.
; 0: Alcor Micro USB Smart Card Reader 0
; 1: Generic Smart Card Reader Interface 0
; 2: SCM Microsystems Inc. SCR33x USB Smart Card Reader 0
; 

; Synchronously wait 30 seconds for a card to be inserted or removed from any of the above readers.
$oJson2 = ObjCreate("Chilkat.JsonObject")
$bSuccess = $oScard.GetStatusChange(30000,$oStReaders,$oJson2)
If ($bSuccess = False) Then
    ConsoleWrite($oScard.LastErrorText & @CRLF)
    Exit
EndIf

ConsoleWrite(" " & @CRLF)

; Let's see what happened...
$oJson2.EmitCompact = False
ConsoleWrite($oJson2.Emit() & @CRLF)
ConsoleWrite(" " & @CRLF)

; This is what json2 contains.
; A card was inserted into the reader named "SCM Microsystems Inc. SCR33x USB Smart Card Reader 0"
; The "numChanged" indicates that one reader's status changed.  
; The "changed":true indicates the reader that changed.   The state is now "present".

; {
;   "numChanged": 1,
;   "reader": [
;     {
;       "name": "Alcor Micro USB Smart Card Reader 0",
;       "changed": false,
;       "state": "empty"
;     },
;     {
;       "name": "Generic Smart Card Reader Interface 0",
;       "changed": false,
;       "state": "present",
;       "atr": "3BFC180000813180459067464A00641606F2727E00E0"
;     },
;     {
;       "name": "SCM Microsystems Inc. SCR33x USB Smart Card Reader 0",
;       "changed": true,
;       "state": "present",
;       "atr": "3BDF96FF8131FE455A018048494443313158587300011B09"
;     }
;   ]
; }

; Find the reader that changed...
Local $bChanged
Local $state
Local $sAtr

Local $iNumChanged = $oJson2.IntOf("numChanged")
ConsoleWrite("number of readers with a changed state: " & $iNumChanged & @CRLF)

$i = 0
$iCount_i = $oJson2.SizeOfArray("reader")
While $i < $iCount_i
    $oJson2.I = $i
    $bChanged = $oJson2.BoolOf("reader[i].changed")
    If ($bChanged = True) Then
        $sName = $oJson2.StringOf("reader[i].name")
        $state = $oJson2.StringOf("reader[i].state")

        ConsoleWrite("Changed: " & @CRLF)
        ConsoleWrite("    reader name: " & $sName & @CRLF)
        ConsoleWrite("    new state: " & $state & @CRLF)

        ; If a card is now in this reader, we should have the ATR of the card..
        If ($oJson2.HasMember("reader[i].atr") = True) Then
            $sAtr = $oJson2.StringOf("reader[i].atr")
            ConsoleWrite("    ATR of card inserted into this reader: " & $sAtr & @CRLF)
        EndIf

    EndIf

    $i = $i + 1
Wend

; The output from the above loop:

; number of readers with a changed state: 1
; Changed: 
;     reader name: SCM Microsystems Inc. SCR33x USB Smart Card Reader 0
;     new state: present
;     ATR of card inserted into this reader: 3BDF96FF8131FE455A018048494443313158587300011B09

; Applications should always release the context when finished.
$bSuccess = $oScard.ReleaseContext()
If ($bSuccess = False) Then
    ConsoleWrite($oScard.LastErrorText & @CRLF)
EndIf