智能卡终端删除:SCARD_E_NO_SERVICE CardException

JR *_*ily 8 java smartcard pcsc windows-8

我正在开发一个smartcardio用于处理智能卡的Java应用程序.必须有一个可以移除其USB读卡器,然后再次插入它而无需再次启动小程序.

我正在使用terminals()waitForChange()方法来检测终端更改,它在Linux,MacOS和Win7上运行良好.

但是在Windows 8(仅限Windows 8)上,删除最后一个终端后,这些方法抛出一个SCARD_E_NO_SERVICE CardException,并且不再检测到任何更改.

我不确定它所说的"服务"是什么.但是当我打电话TerminalFactory.getDefault()给一个TerminalFactory单身人士时,我认为这是在我的主题中启动的.而且我认为这个单例可能有办法管理底层服务,这就是被打破的.

有没有人smartcardio在Windows 8 上如何管理终端断开?

小智 16

这篇文章很老了,但是对我来说修复Windows 8中描述的问题非常有用.

来自JR Utily的解决方案无法完全发挥作用:如果读取器已拔下插头再插入,则CardTerminal实例上存在错误.

所以我添加了一些代码来清除终端列表,如下面的代码所示.

        Class pcscterminal = Class.forName("sun.security.smartcardio.PCSCTerminals");
        Field contextId = pcscterminal.getDeclaredField("contextId");
        contextId.setAccessible(true);

        if(contextId.getLong(pcscterminal) != 0L)
        {
            // First get a new context value
            Class pcsc = Class.forName("sun.security.smartcardio.PCSC");
            Method SCardEstablishContext = pcsc.getDeclaredMethod(
                                               "SCardEstablishContext",
                                               new Class[] {Integer.TYPE }
                                           );
            SCardEstablishContext.setAccessible(true);

            Field SCARD_SCOPE_USER = pcsc.getDeclaredField("SCARD_SCOPE_USER");
            SCARD_SCOPE_USER.setAccessible(true);

            long newId = ((Long)SCardEstablishContext.invoke(pcsc, 
                    new Object[] { SCARD_SCOPE_USER.getInt(pcsc) }
            ));
            contextId.setLong(pcscterminal, newId);


            // Then clear the terminals in cache
            TerminalFactory factory = TerminalFactory.getDefault();
            CardTerminals terminals = factory.terminals();
            Field fieldTerminals = pcscterminal.getDeclaredField("terminals");
            fieldTerminals.setAccessible(true);
            Class classMap = Class.forName("java.util.Map");
            Method clearMap = classMap.getDeclaredMethod("clear");

            clearMap.invoke(fieldTerminals.get(terminals));
        }
Run Code Online (Sandbox Code Playgroud)