java智能卡终端移除:SCARD_E_无服务卡例外
我正在开发一个Java应用程序,它使用smartcardio
来处理智能卡。
必须能够让其中一个卸下USB读卡器,然后再次插入,而无需再次启动小程序
我正在使用terminals()
和waitForChange()
方法来检测终端更改,它在Linux、MacOS和Win7上运行良好
但是在Windows 8(仅限Windows 8)上,在移除最后一个终端后,这些方法抛出一个SCARD_E_NO_SERVICE
{
我不知道它在说什么“服务”。但我认为这是在我调用TerminalFactory.getDefault()
以获得TerminalFactory
单例时在我的线程中启动的。我认为这个单身者可能有办法管理底层服务,而这正是被打破的
有人知道如何在Windows8上管理终端断开与smartcardio
的连接吗
# 1 楼答案
(这只是一条评论,但我没有足够的代表发表评论。)
它所指的服务是Windows智能卡服务,也称为智能卡资源管理器。如果你打开服务MMC控制台,你会看到它的启动类型设置为手动(触发启动)。在Windows 8中,此服务更改为仅在智能卡读卡器连接到系统时运行(以节省资源),并且在删除最后一个读卡器时,该服务将自动停止。停止服务会使任何未完成的句柄无效
本机Windows解决方案是调用SCardAccessStartedEvent并使用它返回的句柄等待服务启动,然后使用SCardEstablishContext再次连接到资源管理器
# 2 楼答案
我找到了一种方法,但它使用的是反射代码。我宁愿找到一种更干净的方法,但似乎没有管理智能卡上下文的官方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
之前完成# 3 楼答案
这篇文章已经很老了,但它对我解决Windows 8上描述的问题很有用
来自JR Utily的解决方案没有完全起作用:如果一个读卡器被拔出,然后再次插入,CardTerminal实例上就出现了错误
因此,我添加了一些代码来清除终端列表,如下面的代码所示