首页 新闻 赞助 找找看

VB2005操作D8读卡器

0
悬赏园豆:50 [已解决问题] 解决于 2010-08-18 13:53

我使用vb2005调用德卡提供的dll读取卡内信息时遇到了2个问题
一是在读某些块地址时,会报“尝试读取或写入受保护的内存。这通常指示其他内存已损坏。”
二是当返回到应答码为读取成功时,却接收不到任何数据

德卡提供的API里dll中读取卡内信息的函数定义为:

int dc_read(int icdev,unsigned char _Adr,unsigned char *_Data);

 

 


这里_Data就是返回数据的地方
我在vb2005中声明的函数为

 

Private Declare Function dc_read Lib "dcrf32.dll" (ByVal icdev As Integer, ByVal _adr As Char, ByRef dataBuf As String) As Integer


自定义读卡的函数为:

'读取单程票数据
Public Function ReadTkt() As Boolean
Dim st As Integer '读取结果
ReadTkt = False

frmCardReader.Log(
"开始读单程票数据...")
'单程票共占用48字节
Try
'读发行区,8字节
st = dc_read(icdev, ChrW(4), dataBuf)
If (st <> 0) Then ' 读卡失败
frmCardReader.Log("读取单程票(发行区)信息失败")
Exit Function
End If
'读发行区信息成功,截取dataBuf,转换为需要的数据
frmCardReader.Log("读取单程票(发行区)信息成功:" & dataBuf)
Catch ex As Exception
ReadTkt
= False
frmCardReader.Log(ex.Message)
MsgBox("读单程票失败,错误代码:[" & st & "]")
End Try
End Function

 

 


望各位看到帖子的朋友费费心,很急,多谢大家了

问题补充: 我将函数声明改为 Private Declare Function dc_read Lib "dcrf32.dll" (ByVal icdev As Integer, ByVal _adr As Byte, <MarshalAs(UnmanagedType.LPArray)> ByRef dataBuf() As Byte) As Integer 还是读不出来,块地址_Adr应该定义为什么类型,按照文档上说MF卡的4-15数据块都是可读写的。但为什么要报“尝试读取或写入受保护的内存”的错或是返回应答码正确,但_Data却没有值呢 问题已经解决了,我一开始是按照德卡提供的VB6.0的例子来写的,没有注意到VB2005与VB6数据类型上的区别。现在把_data还是定义为String类型,但是需要为其定义一个初始大小。我一次需要读8个字节,因此 Dim dataBuf As String dataBuf = new String(CChar(" "), 16) 这样就可以了。另外对于VB6升级到VB2005,通常需要将Long变为Int,Int变为Short,String * 32之类转换为String并赋予初始大小
诚实小郎君的主页 诚实小郎君 | 初学一级 | 园豆:3
提问于:2010-08-17 17:25
< >
分享
最佳答案
0

//函数原型:
        //int __stdcall CPUPBOC_CardProtocol(HANDLE hPort,int iProtocol,
        //                                   int iInDataLen,unsigned char *pucInData,
        //                                   int *iOpState,
        //                                   int *iOutDataLen,unsigned char *pucOutData)
        //函 数 名 : CPUPBOC_CardProtocol
        //函数功能 : 发chip指令
        //处理过程 :
        //返 回 值 : int 操作状态字:
        //参数说明 : HANDLE hPort,
        //            int iProtocol,     协议 T=0,1
        //            int iInDataLen,     C-APDU包长度
        //            unsigned char *pucInData,  C-APDU包
        //            int *iOpState,     返回操作状态字P:
        //                                        P=Y(0X59) 成功,89
        //                                        P=N(0X4E) 操作不成功,78
        //                                        P=E(0X45) 卡机无卡,69
        //                                        P=W(0X57) 卡不在允许操作的位置上 87
        //            int *iOutDataLen,    C-APDU操作返回包长度
        //            unsigned char *pucOutData  C-APDU操作返回包
        [DllImport("DeCard_D8.dll", EntryPoint = "CPUPBOC_CardProtocol", CharSet = CharSet.Auto)]
        private static extern int _CardProtocol(int hPort, int iProtocol, int iInDataLen,
            byte[] pucInData, ref int iOpState, ref int iOutDataLen, [Out, MarshalAs(UnmanagedType.LPArray)]byte[] pucOutData);
        #endregion

 

发个c#的给你参考一下。我这个也是操作德卡的

收获园豆:25
kingtiwns | 菜鸟二级 |园豆:260 | 2010-08-17 17:56
还是读不出来,块地址_Adr应该定义为什么类型,按照文档上说MF卡的4-15数据块都是可读写的。但为什么要报“尝试读取或写入受保护的内存”的错或是返回应答码正确,但_Data却没有值呢
诚实小郎君 | 园豆:3 (初学一级) | 2010-08-18 10:21
ByRef dataBuf() As Byte这个要改成数组吧。调用前最好给数组初始化一定的大小
kingtiwns | 园豆:260 (菜鸟二级) | 2010-08-18 10:39
虽然没有说到问题的真正原因,但是还是谢谢你的热心帮助哈
诚实小郎君 | 园豆:3 (初学一级) | 2010-08-18 13:56
其他回答(1)
0

ByRef dataBuf As String

还得指定 CharSet.

char* 在 C++ 是指以 /0 结尾的字符串,也可以表示 char[] 数组(定长字符串).

因为C++中没有 byte,所以字节值用 char 表示.

如果以string 读取无法成功,就说明 char* 代表的是定长字符串,那么你就需要用C#中的byte[] 来接收定长字符串数组,然后再转换成string.

收获园豆:25
Launcher | 园豆:45045 (高人七级) | 2010-08-17 17:33
还是读不出来,块地址_Adr应该定义为什么类型,按照文档上说MF卡的4-15数据块都是可读写的。但为什么要报“尝试读取或写入受保护的内存”的错或是返回应答码正确,但_Data却没有值呢
支持(0) 反对(0) 诚实小郎君 | 园豆:3 (初学一级) | 2010-08-18 10:22
@诚实小郎君:如果 C++ 的函数原形定义为 char *_Data ,那么就是要求调用方传入有效的char[]数组,同时函数原形还应该提供一个入参 int size,该传入参数指示你传入的char[]的长度,你防止函数在char*++时越界。如果函数原形定义为char& _Data ,那就是告诉你,它会为你分配一个char[] 数组,同时它还要提供一个传出参数,int& size,告诉你它分配了多大的char数组,以防止你使用时越界。
支持(0) 反对(0) Launcher | 园豆:45045 (高人七级) | 2010-08-18 14:54
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册