我正在尝试检测卡何时插入读卡器。 如果我像这样做一个讨厌的轮询循环:
public struct SCARD_READERSTATE
{
[MarshalAs(UnmanagedType.LPWStr)]
public string szReader;
public byte[] pvUserData;
public byte[] rgbAtr;
public uint dwCurrentState;
public uint dwEventState;
public uint cbAtr;
}
byte[] atr = null;
SCARD_READERSTATE[] rs = new SCARD_READERSTATE[1];
rs[0].szReader = readersList[0];
rs[0].dwCurrentState = SCARD_STATE_UNAWARE;
rs[0].dwEventState = SCARD_STATE_PRESENT;
int hctx = hContext.ToInt32();
var cardResult = SCardGetStatusChange(hctx, 100, rs, 1);
if (cardResult == 0 && rs[0].cbAtr > 0 && rs[0].rgbAtr != null)
{
atr = new byte[rs[0].cbAtr];
Array.Copy(rs[0].rgbAtr, atr, rs[0].cbAtr);
}
while ( (rs[0].dwCurrentState & SCARD_STATE_PRESENT) == 0)
{
rs = new SCARD_READERSTATE[1];
rs[0].szReader = readersList[0];
//rs[0].dwCurrentState = SCARD_STATE_PRESENT;
//rs[0].dwEventState = SCARD_STATE_PRESENT;
SCardGetStatusChange(hctx, 100000000, rs, 1);
System.Threading.Thread.Sleep(1000);
}
它有效,但它有一个令人讨厌的线程睡眠。理想情况下,我想在后台线程上对SCardGetStatusChange进行阻塞调用,然后显示事件。
显然通过将szReader设置为值“\\?PnP?\ Notification”,只要结构中的其他内容都为0,它就应该阻塞。
我已将代码更改为
rs[0].szReader = "\\\\?PnP?\\Notification";
rs[0].cbAtr = 0;
rs[0].dwCurrentState = 0;
rs[0].dwEventState = 0;
rs[0].pvUserData = new byte[0];
rs[0].rgbAtr = new byte0];
SCardGetStatusChange(hctx, 100000000, rs, 1);
但它只会立即返回成功结果。任何pInvoke大师都可以看到有什么问题吗?
答案 0 :(得分:4)
在您的示例中,如果您将dwEventState复制到dwCurrentState然后重置dwEventState,那么对SCardGetStatusChange
的第二次调用应该会阻止,因此不需要睡眠。
“\\?PnP?\ Notification”结构用于告诉您何时连接了新的智能卡阅读器,而不是在插入卡时。 From the MSDN page on SCardGetStatusChange:
要获知新智能卡读卡器的到达,请将SCARD_READERSTATE结构的szReader成员设置为“\\?PnP?\ Notification”,并将该结构的所有其他成员设置为零。
使用“\\?PnP?\ Notification”结构时:
pvUserData
和rgbAttr
字段应设为null
new byte[0]
是指向零长度数组的有效指针,但API需要的是空指针或零值。rs[0].dwCurrentState = (readerCount << 16);