I've had this software running in production for years and never seen this problem before. I just received a new laptop (HP EliteBook 8470p) that has a built-in Alcor Micro USB Smart Card Reader.
The code below will list all readers on a system and seems to work fine. Some of our systems will have 3 or 4 readers plugged in to a single computer. It's been tested with a dozen or so models with no issues.
Strangely, the Alcor reader will only get listed when a Smart Card is inserted. If I look at it in Device Manager, it doesn't show up under the "Smart card readers" until a card is inserted, too (unless I go to View > Show Hidden Devices).
Does anyone know why this is or if there's a way to make sure it gets listed in my software?
Thank you.
The code:
[DllImport("WINSCARD.DLL", EntryPoint = "SCardEstablishContext", CharSet = CharSet.Unicode, SetLastError = true)]
static internal extern uint EstablishContext(ScopeOption scope, IntPtr reserved1,
IntPtr reserved2, ref SmartcardContextSafeHandle context);
[DllImport("WINSCARD.DLL", EntryPoint = "SCardListReaders", CharSet = CharSet.Unicode, SetLastError = true)]
static internal extern uint ListReaders(SmartcardContextSafeHandle context, string groups,
string readers, ref int size);
private bool EstablishContext()
{
if ((this.HasContext))
{
return true;
}
this._lastErrorCode =
(SmartcardErrorCode)UnsafeNativeMethods.EstablishContext(ScopeOption.System,
IntPtr.Zero, IntPtr.Zero, ref this._context);
return (this._lastErrorCode == SmartcardErrorCode.None);
}
public ArrayList ListReaders()
{
ArrayList result = new ArrayList();
//Make sure a context has been established before
//retrieving the list of smartcard readers.
if (this.EstablishContext())
{
//Ask for the size of the buffer first.
int size = this.GetReaderListBufferSize();
//Allocate a string of the proper size in which
//to store the list of smartcard readers.
string readerList = new string('\0', size);
//Retrieve the list of smartcard readers.
this._lastErrorCode =
(SmartcardErrorCode)UnsafeNativeMethods.ListReaders(this._context,
null, readerList, ref size);
if ((this._lastErrorCode == SmartcardErrorCode.None))
{
//Extract each reader from the returned list.
//The readerList string will contain a multi-string of
//the reader names, i.e. they are seperated by 0x00
//characters.
string readerName = string.Empty;
for (int i = 0; i <= readerList.Length - 1; i++)
{
if ((readerList[i] == '\0'))
{
if ((readerName.Length > 0))
{
//We have a smartcard reader's name.
result.Add(readerName);
readerName = string.Empty;
}
}
else
{
//Append the found character.
readerName += new string(readerList[i], 1);
}
}
}
}
return result;
}
Btw, this code was written by someone else who I'm guessing (by the over-abundance of comments) found it somewhere else online. I'm somewhat familiar with it but never gotten too deep into it. I've tried making several tweaks to it and can't get it to list that Alcor reader at all.
Thanks!