我试图学习在C#中使用winscard.dll,但在运行SCardTransmit((时遇到了问题,它总是给我返回一个空缓冲区。
这是我的测试代码:
class Program
{
static void Main(string[] args)
{
IntPtr _hContext;
IntPtr _hCard;
uint _activeProtocol;
int retcode = 0;
// Establish context:
retcode = PCSCLite.SCardEstablishContext(PCSCLite.SCARD_SCOPE_USER, IntPtr.Zero, IntPtr.Zero, out _hContext);
// List Readers:
uint pcchReaders = 0;
retcode = PCSCLite.SCardListReaders(_hContext, null, null, ref pcchReaders);
byte[] mszGroups = new byte[pcchReaders];
retcode = PCSCLite.SCardListReaders(_hContext, null, mszGroups, ref pcchReaders);
string sBuffer = Encoding.ASCII.GetString(mszGroups);
int nullIndex = -1;
char nullchar = (char)0;
int len = (int)pcchReaders;
List<String> readers = new List<String>();
while(sBuffer[0] != (char)0)
{
nullIndex = sBuffer.IndexOf(nullchar);
string reader = sBuffer.Substring(0, nullIndex);
readers.Add(reader);
len -= (reader.Length + 1);
sBuffer = sBuffer.Substring(nullIndex + 1, len);
}
foreach(var reader in readers)
{
Console.WriteLine(reader);
}
// Connect
retcode = PCSCLite.SCardConnect(_hContext, readers[1], PCSCLite.SCARD_SHARE_SHARED, PCSCLite.SCARD_PROTOCOL_T0, out _hCard, out _activeProtocol);
// Transmit
//SCARD_IO_REQUEST pioSendPci = _activeProtocol == 1 ? PCSCLite.SCARD_PCI_T0() : PCSCLite.SCARD_PCI_T1(); // based on current active protocol
SCARD_IO_REQUEST pioSendPci = new SCARD_IO_REQUEST();
pioSendPci.cbPciLength = 8;
byte[] pbSendBuffer = { 0x00, 0xA4, 0x04, 0x0C, 0x00 };
uint cbSendLength = (uint)pbSendBuffer.Length;
byte[] pbRecvBuffer = new byte[263];
uint pcbRecvLength = 0;
retcode = PCSCLite.SCardTransmit(_hCard, ref pioSendPci, pbSendBuffer, cbSendLength, IntPtr.Zero, pbRecvBuffer, ref pcbRecvLength);
我如何整理winscard.dll的源代码可以在这里找到:LibPCSCLite
我如何运行它:
首先我创建了C#类库(LibPCSCLite(,然后构建它以获得LibPCSCLite.dll其次,我创建了C#控制台程序,添加了对LibPCSCLite.dll的引用,并运行/调试控制台。
我使用的是Windows 10,使用的是VS 2019和Net Framework 3.5版本我已经在NetFramework4.5版本上测试过了,仍然没有任何区别。更改平台目标(AnyCPUx86(也没有任何效果。
当运行SELECT FILE命令时,我在pbRecvBuffer上得到了全零,甚至不是SW字节,但在pcbRecvLength变量中得到了值20,我认为它是FCI+SW字节长度。
我使用的读卡器是OMNIKEY 5321非接触式
当运行SELECT FILE命令时,我在pbRecvBuffer上得到了全零,甚至不是SW字节,但在pcbRecvLength变量中得到了值20,我认为它是FCI+SW字节长度。
这没关系,因为您传递的pcbRecvLength等于零。pcbRecvLength的值提供pbRecvBuffer参数的长度(以字节为单位(。所以,零的意思是";"零缓冲区大小";,即没有用于复制结果的目的地缓冲区。执行SCardTransmit后,您在pcbRecvLength中有从智能卡接收的实际字节数:20字节。
尝试用pbRecvBuffer的实际大小分配pcbRecvLength。