好吧,我找到了解决方案。我已经从他们的 GitHub 页面下载了 PC/SC-Sharp 的源代码并开始分析,问题出在方法SCardListReaders中,该方法具有参数pcchReaders
并且该参数太小并导致异常,来自 MSDN:
mszReaders 缓冲区的长度(以字符为单位)。此参数接收多字符串结构的实际长度,包括所有尾随空字符。如果缓冲区长度指定为 SCARD_AUTOALLOCATE,则 mszReaders 将转换为指向字节指针的指针,并接收包含多字符串结构的内存块的地址。必须使用 SCardFreeMemory 释放此内存块。
在 pcsc-sharp 的ListReaders
方法(WinSCardAPI)中这样调用:
public SCardError ListReaders(IntPtr hContext, string[] groups, out string[] readers) {
var dwReaders = 0;
// initialize groups array
byte[] mszGroups = null;
if (groups != null)
mszGroups = SCardHelper.ConvertToByteArray(groups, TextEncoding);
// determine the needed buffer size
var rc = SCardHelper.ToSCardError(
SCardListReaders(hContext,
mszGroups,
null,
ref dwReaders));
if (rc != SCardError.Success) {
readers = null;
return rc;
}
// initialize array
var mszReaders = new byte[dwReaders * sizeof(char)];
rc = SCardHelper.ToSCardError(
SCardListReaders(hContext,
mszGroups,
mszReaders,
ref dwReaders));
readers = (rc == SCardError.Success)
? SCardHelper.ConvertToStringArray(mszReaders, TextEncoding)
: null;
return rc;
}
第一次,它是调用SCardListReaders
方法来确定所需的缓冲区大小,mszReaders
参数设置为null
,所以根据 MSDN:
列出提供的读卡器组中的读卡器的多字符串。如果此值为 NULL,SCardListReaders 将忽略 pcchReaders 中提供的缓冲区长度,将如果此参数不是 NULL 则将返回的缓冲区长度写入 pcchReaders,并返回成功代码。
所以它应该分配给dwReaders
正确的缓冲区大小,用于获取连接的读者列表。好吧,它在我的 Windows 10 pro 机器上正常工作,阅读器直接连接,但通过瘦客户端连接到 Windows 2008 r2 服务器,它返回相同的值(它是37
),但该值导致InsufficientBuffer
异常。
因此,我开始调整该值并手动设置(在 Windows 2008 r2 服务器内调试),我发现如果将该值设置为48
(或更高)它将起作用。我不知道是什么原因导致该SCardListReaders
方法返回的参数值不足,但我设法在第二次通过之前手动将该值加倍,所以新版本ListReaders()
看起来像这样:
public SCardError ListReaders(IntPtr hContext, string[] groups, out string[] readers) {
var dwReaders = 0;
// initialize groups array
byte[] mszGroups = null;
if (groups != null)
mszGroups = SCardHelper.ConvertToByteArray(groups, TextEncoding);
// determine the needed buffer size
var rc = SCardHelper.ToSCardError(
SCardListReaders(hContext,
mszGroups,
null,
ref dwReaders));
if (rc != SCardError.Success) {
readers = null;
return rc;
}
//doubling buffer size to work through thin clients
dwReaders *= 2; // <------------------ New line
// initialize array
var mszReaders = new byte[dwReaders * sizeof(char)];
rc = SCardHelper.ToSCardError(
SCardListReaders(hContext,
mszGroups,
mszReaders,
ref dwReaders));
readers = (rc == SCardError.Success)
? SCardHelper.ConvertToStringArray(mszReaders, TextEncoding)
: null;
return rc;
}
所以它现在正在工作,如果你有任何想法和少一点“hacky”的解决方案,也许我做错了什么,或者它应该通过瘦客户端以不同的方式工作,这是一个错误或什么,请随时发表评论!