Search code examples
c#smartcardpcscgemalto

Cannot access Smart Card at first attempt, any other is successful


I have a trouble with PCSC Reader and Smart card. I am not able to access the card with my GUI application. It works like a charm in the console example app.
I receive Exception:

SCard.Connect Error 0x8010000B: The smart card cannot be accessed because of other connections outstanding!
A first chance exception of type 'GS.SCard.WinSCardException' occurred in GS.CSharpPCSC.dll

But when I remove the card and reinsert it, it works fine.
I've thought that the card is accessed by other process in my Windows machine at the moment of insertion, so I created a while which would catch especially situation when ret value is equal to -2146435061 in WinSCardException and continue the loop, or break if connection is OK.
Steps I do to connect to the card:

PCSCReader reader = new PCSCReader();
string[] readers = reader.SCard.ListReaders(); 
// Returns 3 readers (even though I have 2 connected, but when I once connected the third one it now appears always) - why?
// Here with GUI I choose interested reader (which is really connected)
reader.SCard.ReleaseContext();
reader.Disconnect(); // In case there is any reader connected
// Here I stop my worker so that It will not try to access reader when it is not connected
reader.Connect(readers[1]); // For example let's connect to reader 1
// Now the worker starts working

//...DoWork method of worker:
while(true)
{
  try {reader.ActivateCard(); break;} // break if successfully connected
  // If the ex status is positive then there is some other issue which is handled by bigger try-catch, but for case ret is -2146435061 i want to continue the loop
  catch (WinSCardException ex) {if (ex.Status > -100) throw (ex); }
  // But this throw Exception over and over again

Need help please.
I use this wrapper: http://www.smartcard-magic.net/en/pc-sc-reader/csharppcsc-wrapper/
Example program look almost the same, but does not throw any error.

using System;
using System.Diagnostics;
using GS.Apdu;
using GS.PCSC;
using GS.SCard;
using GS.SCard.Const;
using GS.Util.Hex;

namespace ExamplePCSCReader
{
    class Program
    {
        static void Main( string[] args )
        {
            ConsoleTraceListener consoleTraceListener = new ConsoleTraceListener();
            Trace.Listeners.Add(consoleTraceListener);

            PCSCReader reader = new PCSCReader();

            try
            {
                reader.Connect();
                reader.ActivateCard();

                RespApdu respApdu = reader.Exchange("00 B0 00 00 0A"); // Get Card UID ...
                if (respApdu.SW1SW2 == 0x9000)
                {
                    Console.WriteLine("ICCID  = 0x" + HexFormatting.ToHexString(respApdu.Data, true));
                }
            }
            catch (WinSCardException ex)
            {
                Console.WriteLine( ex.WinSCardFunctionName + " Error 0x" + 
                                   ex.Status.ToString( "X08" ) + ": " + ex.Message );
            }
            catch (Exception ex)
            {
                Console.WriteLine( ex.Message );
            }
            finally
            {
                reader.Disconnect();
                Console.WriteLine( "Please press any key..." );
                Console.ReadLine();
            }
        }
    }
}
}

Solution

  • For the problem about accessing reader - the solution is to share the reader with command:

    reader.ActivateCard(GS.SCard.Const.SCARD_SHARE_MODE.Shared, GS.SCard.Const.SCARD_PROTOCOL.Tx);
    

    The problem with listing not extisting readers was because if the context was not established, the wrapper was taking list of readers from Windows Registry. When I established context before I list readers - only connected readers appear.

    reader.SCard.EstablishContext();
    readers = reader.SCard.ListReaders();