c# - 使用 SCardGetStatusChange 通知卡插入/移除而不轮询

标签 c# pinvoke smartcard

我正在尝试检测卡片何时插入读卡器。 如果我像这样进行讨厌的轮询循环:

      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 大师都可以看出问题所在吗?

最佳答案

  1. 在您的示例中,第二次调用 SCardGetStatusChange如果您将 dwEventState 复制到 dwCurrentState 然后重置 dwEventState,应该会阻塞,因此不需要 sleep 。

  2. “\\?PnP?\Notification”结构是在连接新智能卡读卡器时通知您,而不是在插入卡时通知您。 From the MSDN page on SCardGetStatusChange :

    To be notified of the arrival of a new smart card reader, set the szReader member of a SCARD_READERSTATE structure to "\\?PnP?\Notification", and set all of the other members of that structure to zero.

  3. 当使用“\\?PnP?\Notification”结构时:

    • pvUserDatargbAttr字段应设置为 null
      • 一个new byte[0]是指向零长度数组的有效指针,但 API 在这里需要的是空指针或零值)
    • dwCurrentState 的高 16 位应包含当前读取器计数
      • rs[0].dwCurrentState = (readerCount << 16);
      • MSDN 页面目前在这一点上不准确。

关于c# - 使用 SCardGetStatusChange 通知卡插入/移除而不轮询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16370909/

相关文章:

c# - 如何在 MVC 中跟踪以前的 Urls

c# - 在 C# 上使用 CreateFile 返回 isInvalid = true

c# - 如何在不调用函数的情况下检查C#中是否存在DLL入口点

c - 无法编译读取智能卡的 C 应用程序

google-chrome - Chrome中电子智能卡的数字签名

c# - 原始类型的最佳序列化

c# - 为Caliburn.Micro Action Message指定自定义防护属性

c# - 用于滑入/滑出页面的 WPF 框架动画无法与数据触发器一起正常工作

c# - 如何在 C# 中创建具有动态属性和属性的结构

smartcard - 为什么真正的 POS 终端不使用 PSE(2PAY 或 1PAY)?