首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >智能卡终端移除: SCARD_E_NO_SERVICE CardException

智能卡终端移除: SCARD_E_NO_SERVICE CardException
EN

Stack Overflow用户
提问于 2013-06-04 23:31:21
回答 3查看 5.6K关注 0票数 9

我正在开发一个Java应用程序,它使用smartcardio来处理智能卡。必须能够将其USB卡读卡器取出,然后重新插入,而无需再次启动小程序。

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

但在Windows8(仅限Windows8)上,在移除最后一个终端后,这些方法会抛出SCARD_E_NO_SERVICE CardException,并且不会检测到任何其他更改。

我不知道它说的是什么“服务”。但是当我调用TerminalFactory.getDefault()来拥有一个TerminalFactory单例时,我想这是在我的线程中启动的。我认为这个单例可能有一种方法来管理底层服务,这就是问题所在。

有谁知道如何在Windows8上使用smartcardio管理终端断开连接吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-10-21 00:09:18

这篇文章很老了,但它对我解决Windows8上描述的问题很有用。

JR Utily的解决方案并不完全有效:在读卡器拔出然后再次插入的情况下,CardTerminal实例上会出现错误。

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

代码语言:javascript
复制
        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));
        }
票数 18
EN

Stack Overflow用户

发布于 2013-06-07 23:35:33

我已经找到了一种方法,但它使用的是反射代码。我更希望找到一种更干净的方法,但似乎没有官方API来管理智能卡上下文。所有类都是私有的。

sun.security.smartcardio.PCSCTerminals (http://www.docjar.com/html/api/sun/security/smartcardio/PCSCTerminals.java.html)的initContext()方法防止新线程在第一个线程初始化后获得新的上下文:该方法被调用,但该上下文被视为单例,并且不会重新初始化。

使用java.lang.reflect遍历private,可以强制创建一个新的上下文,并将其新的id存储为“官方”contextId。这应该在实例化新的TerminalFactory之前完成。

代码语言:javascript
复制
    // ...
    Class pcscterminal = Class.forName("sun.security.smartcardio.PCSCTerminals");
    Field contextId = pcscterminal.getDeclaredField("contextId");
    contextId.setAccessible(true);

    if(contextId.getLong(pcscterminal) != 0L)
    {
        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[] { Integer.valueOf(SCARD_SCOPE_USER.getInt(pcsc)) }
              )).longValue();
        contextId.setLong(pcscterminal, newId);
    }
    // ...
票数 4
EN

Stack Overflow用户

发布于 2013-06-20 16:46:26

(这只是一个评论,但我没有足够的代表来发表评论。)

它所指的服务是Windows智能卡服务,也称为智能卡资源管理器。如果您打开服务MMC控制台,您将看到它的启动类型设置为手动(触发器启动)。在Windows 8中,此服务被更改为仅在智能卡读卡器连接到系统时运行(以节省资源),并在移除最后一个读卡器时自动停止该服务。停止该服务将使所有未完成的句柄失效。

本机Windows解决方案是调用SCardAccessStartedEvent并使用它返回的句柄等待服务启动,然后使用SCardEstablishContext再次连接到资源管理器。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16921785

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档