Smartcard terminal removal : SCARD_E_NO_SERVICE CardException

前端 未结 3 1784
北恋
北恋 2020-12-05 16:11

I am working on an Java application which uses smartcardio to work with smartcard. It must be possible to have one removing its USB card reader and then inserti

3条回答
  •  南笙
    南笙 (楼主)
    2020-12-05 16:47

    This post is quite old, but it has been useful for me to fix the problem described on Windows 8.

    The solution from JR Utily did not work fully: in case of a reader unplugged then plugged again, there were errors on the CardTerminal instance.

    So I added some code to clear the terminals list, as you can see in the code below.

            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));
            }
    

提交回复
热议问题