在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
最近做一个读市民卡的项目,读卡器公司提供的读市民卡dll是用C++写的。 下面记录一些自己的心得,供需要的朋友参考。 声明dll函数要加上stdcall关键字,否则可能会报地址非法的错误。
代码: unit cMain; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, DB, ADODB, StdCtrls, ComCtrls,ActiveX, ExtCtrls; type TForm1 = class(TForm) btnReadICard: TButton; Memo1: TMemo; procedure btnReadICardClick(Sender: TObject); private { Private declarations } public { Public declarations } end; //2014-12-11 type PICC_CONFIG=^ICC_CONFIG; ICC_CONFIG=record port:Integer; baud:Integer; timeout:Integer; PSAMSlot:Integer; ICCSlot:Integer; end; // ICC_CONFIG=record // port:Cardinal; // baud:Cardinal; // timeout:Cardinal; // PSAMSlot:longword; // ICCSlot:longword; // end; //2014-12-11 function SIReaderInit(icc_Config0:PICC_CONFIG; hDevReader:PHandle):Integer;stdcall;external 'SI_ICCReader.dll'; //功能:初始化读卡器设备 //参数:icc_Config0 -- 读卡器参数指针 ICC_CONFIG指针为NULL,则采用默认参数初始化,ICC_CONFIG具体定义参考结构定义 // hDevReader 返回读卡器操作句柄 //返回:=0:正常完成初始化 <>0:初始化出错,调用SIGetErrMessage获取具体的错误信息 function SISelectIFD (hDevReader: THandle; IFDType: Integer):Integer;stdcall;external 'SI_ICCReader.dll'; //功能:选择CPU卡(包括社会保障卡/PSAM卡) //参数:hDevReader -- 通过SIReaderInit函数获得的读卡器句柄 // IFDType -- CPU卡类型,参照标准IC卡类型代码表(0x0c:社保卡槽;0x0d:附卡座PSAM卡槽;0x0E为第一个SAM1卡座,0x0F为第二个SAM2卡座) //返回: =0:表示操作成功 <>0:表示操作失败,调用SIGetErrMessage获取具体的错误信息 function GetReaderStatus(hDevReader: THandle;status: PChar):Integer;stdcall;external 'SI_ICCReader.dll'; //功能:获取读卡器状态 给卡片进行上电 //参数:hDevReader -- 通过SIReaderInit函数获得的读卡器句柄 // status: '2' 读卡器已连接并已插入社会保障卡 //返回:=0:表示操作成功 <>0:表示操作失败,调用SIGetErrMessage获取具体的错误信息 function SIReadInfo(hDevReader: THandle;const sDF:PChar; const sEF:PChar; const cRecNo: Byte; sBuffer:PChar):Integer;stdcall;external 'SI_ICCReader.dll'; //功能:读取社保卡记录文件信息 //参数:hDevReader -- 通过SIReaderInit函数获得的读卡器句柄 // sDF:[IN] :对应目录名称如"DF01","3F00"(MF)。 // sEF:[IN] :对应文件名称如"EF01","EF0C"。 // cRecNo:[IN] :对应文件记录号(不是记录标识),如果为0,则表示读取该文件内所有记录,如果为01-n,则表示读取该文件内某一条记录。 // sBuffer[OUT] :返回读取数据,需要预先分配对应文件内的长度,长度为∑(每个记录字节数) + 1 //返回:=0:表示操作成功 <>0:表示操作失败,调用SIGetErrMessage获取具体的错误信息 procedure SIGetErrMessage(nErrNo:Integer;sErrMessage:PChar);stdcall;external 'SI_ICCReader.dll'; //功能:根据错误代码获取详细错误信息 //参数: NErrNo[IN]:错误代码,见附录错误代码命名方式。 // SErrMessage[OUT]:错误代码所对应的错误信息,已预先分配201个字节长度 var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.btnReadICardClick(Sender: TObject); var nRet:Integer; sBuffer: array[0..200] of Char; sData: array[0..10] of Char; sStatus: array[0..10] of Char; sErrMsg: array[0..50] of Char; icc_Config0:ICC_CONFIG; g_Handle: THandle; begin //端口信息 icc_Config0.port := 100; icc_Config0.baud := 9600; icc_Config0.ICCSlot := 0; icc_Config0.PSAMSlot := 0; icc_Config0.timeout := 0; Memo1.Lines.Clear; nRet := SIReaderInit(@icc_Config0,@g_Handle); if nRet <> 0 then begin // ZeroMemory(@sErrMsg,SizeOf(sErrMsg)); // SIGetErrMessage(nRet, sErrMsg); Memo1.Lines.Add('读卡器初始化失败!,错误代码:') ; end else begin Memo1.Lines.Add('读卡器初始化成功' ); end; //切换卡槽号 nRet := SISelectIFD(g_Handle, $0C); if nRet <> 0 then begin Memo1.Lines.Add('选择社保卡槽失败!') ; end else begin Memo1.Lines.Add('选择社保卡槽成功!'); end; // 获取读卡器状态 给卡片进行上电 FillChar(sStatus,SizeOf(sStatus),#0);//用0填充sStatus nRet := GetReaderStatus(g_Handle, @sStatus[0]); if (nRet = 0)and(sStatus = '2') then begin //附录1:温州市社会保障卡结构 FillChar(sBuffer,SizeOf(sBuffer),#0);//用0填充缓冲区sBuffer nRet := SIReadInfo(g_Handle, '3F00','EF05', 1, sBuffer); Memo1.Lines.Add('卡的识别码:' + sBuffer); FillChar(sBuffer,SizeOf(sBuffer),#0);//用0填充缓冲区sBuffer nRet := SIReadInfo(g_Handle, '3F00','EF05',2, sBuffer); Memo1.Lines.Add('卡的类别:' + sBuffer); FillChar(sBuffer,SizeOf(sBuffer),#0);//用0填充缓冲区sBuffer nRet := SIReadInfo(g_Handle, '3F00','EF05', 3, sBuffer); Memo1.Lines.Add('规范版本:' + sBuffer); FillChar(sBuffer,SizeOf(sBuffer),#0);//用0填充缓冲区sBuffer nRet := SIReadInfo (g_Handle, '3F00','EF05', 4, sBuffer); Memo1.Lines.Add('初始化机构编号:' + sBuffer); FillChar(sBuffer,SizeOf(sBuffer),#0);//用0填充缓冲区sBuffer nRet := SIReadInfo(g_Handle, '3F00','EF05', 5, sBuffer); Memo1.Lines.Add('发卡日期:' + sBuffer); FillChar(sBuffer,SizeOf(sBuffer),#0);//用0填充缓冲区sBuffer nRet := SIReadInfo(g_Handle, '3F00','EF05', 6, sBuffer); Memo1.Lines.Add('卡有效期:' + sBuffer); FillChar(sBuffer,SizeOf(sBuffer),#0);//用0填充缓冲区sBuffer nRet := SIReadInfo(g_Handle, '3F00','EF05', 7, sBuffer); Memo1.Lines.Add('卡号:' + sBuffer); FillChar(sBuffer,SizeOf(sBuffer),#0);//用0填充缓冲区sBuffer nRet := SIReadInfo(g_Handle, '3F00','EF06', 1, sBuffer); Memo1.Lines.Add('公民身份证号码:' + sBuffer); FillChar(sBuffer,SizeOf(sBuffer),#0);//用0填充缓冲区sBuffer nRet := SIReadInfo(g_Handle, '3F00','EF06',2, sBuffer); Memo1.Lines.Add('姓名:' + sBuffer); FillChar(sBuffer,SizeOf(sBuffer),#0);//用0填充缓冲区sBuffer nRet := SIReadInfo(g_Handle, '3F00','EF06', 3, sBuffer); Memo1.Lines.Add('性别:' + sBuffer); FillChar(sBuffer,SizeOf(sBuffer),#0);//用0填充缓冲区sBuffer nRet := SIReadInfo (g_Handle, '3F00','EF06', 4, sBuffer); Memo1.Lines.Add('民族:' + sBuffer); FillChar(sBuffer,SizeOf(sBuffer),#0);//用0填充缓冲区sBuffer nRet := SIReadInfo(g_Handle, '3F00','EF06', 5, sBuffer); Memo1.Lines.Add('出生地:' + sBuffer); FillChar(sBuffer,SizeOf(sBuffer),#0);//用0填充缓冲区sBuffer nRet := SIReadInfo(g_Handle, '3F00','EF06', 6, sBuffer); Memo1.Lines.Add('出生日期:' + sBuffer); end; end; end.
|
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论