Anantha Prasad
Anantha Prasad

Reputation: 53

C# WinScard.SCardListReaders should list only the connected readers (but it is listing all the past installed reader names which is now not connected)

Please go through my below C# code. I am trying to get the list of Smart Card readers that are now connected to my computer. But this function is returning all the smartcard reader names that was connected in the past (I mean not connected now). I want the list of active (presently) connected readers names only. I am not able to understand where is the issue.

I tried a exe from this website which is written and compiled in C. It is showing only the readers that are connected. I compared the code, but I find no difference. Please help to find a fix.

public static int GetPCSCReaders(out List<string> smartCardReaders, out string errMsg)
{
    errMsg = string.Empty;
    byte[] readersList = null;
    smartCardReaders = new List<string>();

    try
    {
        int hContext = 0;
        int ret = SCardEstablishContext(WinSCard.SCARD_SCOPE_USER, 0, 0, ref hContext);
        if (ret != 0)
        {
            errMsg = "WinSCard GetPCSCReader: EstablishContext Error: " + ret.ToString();
            return ret;
        }

        int byteCnt = 0;
        ret = WinSCard.SCardListReaders(hContext, null, null, ref byteCnt);
        if (ret != SCARD_S_SUCCESS)
        {
            errMsg = "WinSCard GetPCSCReader: ListReaders Error: " + ret.ToString();
            return ret;
        }

        readersList = new byte[byteCnt];
        ret = WinSCard.SCardListReaders(hContext, null, readersList, ref byteCnt);
        if (ret != SCARD_S_SUCCESS)
        {
            errMsg = "WinSCard GetPCSCReader: ListReaders Error: " + ret.ToString();
            return ret;
        }

        int indx = 0;
        string readerName = string.Empty;
        int i = 0;

        while (readersList[indx] != 0)
        {
            while (readersList[indx] != 0)
            {
                readerName = readerName + (char)readersList[indx++];
            }

            smartCardReaders.Add(readerName);
            i++;

            readerName = "";
            indx++;
        }

    }
    catch (Exception ex)
    {
        errMsg = ex.Message;
    }
    finally
    {
        readersList = null;
    }
    return 0;
}

Upvotes: 3

Views: 6615

Answers (2)

Anantha Prasad
Anantha Prasad

Reputation: 53

I went through this link, in that page, there is a Tips and Tricks mentioning, "if you invoke SCardListReaders with the hContext parameter set to null, you'll get the list of the installed readers (not the plugged ones !)". As per this, in my code I was having hContext variable as int, I changed it to IntPtr and it made me to list only the readers that are connected. It is Solved and now my code is changed to

public static int GetPCSCReaders(out List<string> smartCardReaders, out string errMsg)
{
    errMsg = string.Empty;
    smartCardReaders = new List<string>();
    IntPtr hContext;

    try
    {
        int ret = SCardEstablishContext(SCARD_SCOPE_USER, IntPtr.Zero, IntPtr.Zero, out hContext);
        if (ret != SCARD_S_SUCCESS)
        {
            errMsg = "WinSCard GetPCSCReader: EstablishContext Error: " + ret.ToString();
            return ret;
        }

        byte[] readersList = null;
        uint byteCnt = 0;
        ret = SCardListReaders(hContext, null, null, ref byteCnt);
        if (ret != SCARD_S_SUCCESS)
        {
            errMsg = "WinSCard GetPCSCReader: ListReaders Error: " + ret.ToString();
            return ret;
        }

        readersList = new byte[byteCnt];
        ret = SCardListReaders(hContext, null, readersList, ref byteCnt);
        if (ret != SCARD_S_SUCCESS)
        {
            errMsg = "WinSCard GetPCSCReader: ListReaders Error: " + ret.ToString();
            return ret;
        }

        int indx = 0;
        string readerName = string.Empty;
        int i = 0;

        while (readersList[indx] != 0)
        {
            while (readersList[indx] != 0)
            {
                readerName = readerName + (char)readersList[indx++];
            }

            smartCardReaders.Add(readerName);
            i++;

            readerName = "";
            indx++;
        }

    }
    catch (Exception ex)
    {
        errMsg = ex.Message;
    }
    finally
    {

    }
    return 0;
}

Upvotes: 2

Dongdong
Dongdong

Reputation: 2508

It's hard to answer the question without a smartcard reader in hand, although I developed on these code just 3 months ago.

My previous code is based on this: https://github.com/nicbedford/CardBrowser/blob/master/PCSC/PCSCReader.cs

It's not working perfectly, you have to detect bugs by yourself. but it exactly helps.

There are different solutions in different windows platforms.

  1. Window 8.1+:

https://code.msdn.microsoft.com/windowsapps/Smart-card-sample-c7d342e0#content

  1. Window 10:

https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/SmartCard

https://learn.microsoft.com/en-us/uwp/api/windows.devices.smartcards

  1. Windows 7+:

https://github.com/nicbedford/CardBrowser/tree/master/PCSC

https://github.com/orouit/SmartcardFramework

https://github.com/danm-de/pcsc-sharp/tree/master/src/PCSC

if you meet issue in translating C++ to C#, you can find all functions here: https://www.pinvoke.net/default.aspx/winscard/SCardTransmit.html just search the function from top left.

Upvotes: 1

Related Questions