新中新二代身份证dll调用问题:
调用这个dll时, 到这个方法: Syn_ReadMsg(nPort, 0, ref CardMsg),就报尝试读取或写入受保护的内存。这通常指示其他内存已损坏 这个错,CardMsg是IDCardData这个结构体,结构体定义如下:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct IDCardData
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] //结构中使用的字串,[]类似限定说明 说明此公共结构传输到非托管代码时封装定义
public string Name; //姓名
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 6)]
public string Sex; //性别
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
public string Nation; //名族
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 18)]
public string Born; //出生日期
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 72)]
public string Address; //住址
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 38)]
public string IDCardNo; //身份证号
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string GrantDept; //发证机关
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 18)]
public string UserLifeBegin; // 有效开始日期
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 18)]
public string UserLifeEnd; // 有效截止日期
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 38)]
public string reserved; // 保留
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 255)]
public string PhotoFileName; // 照片路径
} 原型方法: [DllImport("SynIDCardAPI.dll", EntryPoint = "Syn_ReadMsg", CharSet = CharSet.Ansi)]
public static extern int Syn_ReadMsg(int iPortID, int iIfOpen, ref IDCardData pIDCardData);
就算是新中新光盘里给的示例程序我运行都是报这个错,在论坛里找半天也没找到确切的解决方法,求高手解决
调用这个dll时, 到这个方法: Syn_ReadMsg(nPort, 0, ref CardMsg),就报尝试读取或写入受保护的内存。这通常指示其他内存已损坏 这个错,CardMsg是IDCardData这个结构体,结构体定义如下:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct IDCardData
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] //结构中使用的字串,[]类似限定说明 说明此公共结构传输到非托管代码时封装定义
public string Name; //姓名
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 6)]
public string Sex; //性别
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
public string Nation; //名族
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 18)]
public string Born; //出生日期
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 72)]
public string Address; //住址
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 38)]
public string IDCardNo; //身份证号
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string GrantDept; //发证机关
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 18)]
public string UserLifeBegin; // 有效开始日期
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 18)]
public string UserLifeEnd; // 有效截止日期
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 38)]
public string reserved; // 保留
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 255)]
public string PhotoFileName; // 照片路径
} 原型方法: [DllImport("SynIDCardAPI.dll", EntryPoint = "Syn_ReadMsg", CharSet = CharSet.Ansi)]
public static extern int Syn_ReadMsg(int iPortID, int iIfOpen, ref IDCardData pIDCardData);
就算是新中新光盘里给的示例程序我运行都是报这个错,在论坛里找半天也没找到确切的解决方法,求高手解决
var type = typeof(IDCardData);
var size = Marshal.SizeOf(type);
var p = Marshal.AllocHGlobal(size);
// 调用方法
var data = (IDCardData)Marshal.PtrToStructure(p, type);
Marshal.FreeHGlobal(p)这样试试 data 有没值
var type = typeof(IDCardData);
var size = Marshal.SizeOf(type);
var p = Marshal.AllocHGlobal(size);Syn_ReadMsg( , , p);var pd = p;
IDCardData data = new IDCardData();
data.Name = Marshal.PtrToStringAnsi(pd);
data.Sex = Marshal.PtrToStringAnsi(pd += 32);
data.Nation = Marshal.PtrToStringAnsi(pd += 6);
data.Born = Marshal.PtrToStringAnsi(pd += 20);
data.Address = Marshal.PtrToStringAnsi(pd += 18);
data.IDCardNo = Marshal.PtrToStringAnsi(pd += 72);
data.GrantDept = Marshal.PtrToStringAnsi(pd += 38);
data.UserLifeBegin = Marshal.PtrToStringAnsi(pd += 32);
data.UserLifeEnd = Marshal.PtrToStringAnsi(pd += 18);
data.reserved = Marshal.PtrToStringAnsi(pd += 18);
data.PhotoFileName = Marshal.PtrToStringAnsi(pd += 38);
Marshal.FreeHGlobal(p);
public static extern int Syn_ReadMsg(int iPortID, int iIfOpen, ref IDCardData pIDCardData);
这个是照抄sdk里的,sdk里的例子运行都是一样的错
Syn_ReadMsg( , , p);
这行能不能执行过去?
如果不能,有没有 C/C++ 的函数和结构原型?
// 方法定义
[DllImport("SynIDCardAPI.dll", EntryPoint = "Syn_ReadMsg")]
public static extern int Syn_ReadMsg(int iPortID, int iIfOpen, IntPtr pIDCardData);// 调用
var p = Marshal.AllocHGlobal(10240);
var result = Syn_ReadMsg(0, 0, p);这两行代码执行看看会不会报错
var result = Syn_ReadMsg(0, 0,ref p);
这样调用不会出错,就是赋值进去不了
var result = Syn_ReadMsg( , , p);
byte[] buf = new byte[32];
Marshal.Copy(p, buf, 0, buf.Length);string str1 = Encoding.ASCII.GetString(buf);
string str2 = Encoding.Unicode.GetString(buf);
string str3 = Encoding.UTF8.GetString(buf);
string str4 = Encoding.GetEncoding("GB2312").GetString(buf);这段代码执行下看看 str 1-4 有没哪个不是乱码
var type = typeof(IDCardData);
var size = Marshal.SizeOf(type);
var p = Marshal.AllocHGlobal(size);// 调用方法
nRet = Syn_ReadMsg(0, 0,ref p);
这里返回nRet返回值是0就表示正确返回了,但是返回值不是0,表示返回的值有问题
指针不要 ref ,不然就变成双重指针了,把 ref 修饰去掉,方法定义的地方也去掉,然后运行12楼的代码
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
除非你的dll文档明确表明需要设置Pack,否则建议将其删除
还有,返回值2是什么意思?有没有可能是之前需要调用的初始化之类的函数没完成?
#pragma pack(1)
typedef struct tagIDCardData{
char Name[32]; //姓名
char Sex[6]; //性别
char Nation[20]; //名族
char Born[18]; //出生日期
char Address[72]; //住址
char IDCardNo[38]; //身份证号
char GrantDept[32]; //发证机关
char UserLifeBegin[18]; // 有效开始日期
char UserLifeEnd[18]; // 有效截止日期
char reserved[38]; // 保留
char PhotoFileName[255];// 照片路径
}IDCardData;
#pragma pack()
extern "C"{
//////////////////////////////////////////////////////////////////////////
// SAM端口函数
//
//////////////////////////////////////////////////////////////////////////
int _stdcall Syn_SetMaxRFByte ( int iPort, unsigned char ucByte,int bIfOpen );
int _stdcall Syn_GetCOMBaud ( int iPort, unsigned int * puiBaudRate );
int _stdcall Syn_GetCOMBaudEx ( int iPort ); // 返回实际的波特率,0为失败
int _stdcall Syn_SetCOMBaud ( int iPort, unsigned int uiCurrBaud, unsigned int uiSetBaud );
int _stdcall Syn_OpenPort( int iPort );
int _stdcall Syn_ClosePort( int iPort );
//////////////////////////////////////////////////////////////////////////
// SAM类函数
//
//////////////////////////////////////////////////////////////////////////
int _stdcall Syn_ResetSAM ( int iPort, int iIfOpen );
int _stdcall Syn_GetSAMStatus ( int iPort, int iIfOpen );
int _stdcall Syn_GetSAMID ( int iPort, unsigned char * pucSAMID, int iIfOpen );
int _stdcall Syn_GetSAMIDToStr ( int iPort, char * pcSAMID, int iIfOpen );
//////////////////////////////////////////////////////////////////////////
// 身份证卡类函数
//
//////////////////////////////////////////////////////////////////////////
int _stdcall Syn_StartFindIDCard ( int iPort , unsigned char * pucIIN, int iIfOpen );
int _stdcall Syn_SelectIDCard ( int iPort , unsigned char * pucSN, int iIfOpen );
int _stdcall Syn_ReadBaseMsg (
int iPort ,
unsigned char * pucCHMsg ,
unsigned int * puiCHMsgLen ,
unsigned char * pucPHMsg ,
unsigned int * puiPHMsgLen ,
int iIfOpen);
int _stdcall Syn_ReadIINSNDN ( int iPort , unsigned char * pucIINSNDN , int iIfOpen );
int _stdcall Syn_ReadBaseMsgToFile (
int iPort,
char * pcCHMsgFileName,
unsigned int * puiCHMsgFileLen,
char * pcPHMsgFileName,
unsigned int * puiPHMsgFileLen,
int iIfOpen
);
int _stdcall Syn_ReadIINSNDNToASCII ( int iPort , unsigned char * pucIINSNDN , int iIfOpen );
int _stdcall Syn_ReadNewAppMsg(int iPort , unsigned char * pucAppMsg , unsigned int * puiAppMsgLen , int iIfOpen);
int _stdcall Syn_GetBmp( int iPort , char * Wlt_File );
int _stdcall Syn_ReadMsg( int iPort,int iIfOpen,IDCardData *pIDCardData );
int _stdcall Syn_FindReader();
int _stdcall Syn_BmpToJpeg( char * cBmpName , char * cJpegName);
int _stdcall Syn_GetPhotoBmp(char * cBmpName);
//////////////////////////////////////////////////////////////////////////
// 设置附加功能函数
//
//////////////////////////////////////////////////////////////////////////
int _stdcall Syn_SetPhotoPath( int iOption , char * cPhotoPath );
int _stdcall Syn_SetPhotoType( int iType );
int _stdcall Syn_SetPhotoName( int iType );
int _stdcall Syn_SetSexType( int iType );
int _stdcall Syn_SetNationType( int iType );
int _stdcall Syn_SetBornType( int iType );
int _stdcall Syn_SetUserLifeBType( int iType );
int _stdcall Syn_SetUserLifeEType( int iType ,int iOption);
}
c++里的原型应该是这个
尝试读取或写入受保护的内存。这通常指示其他内存已损坏 这个错,
调用方法:
var p = Marshal.AllocHGlobal(10240);
var result = Syn_ReadMsg(nport, 0, p);
nport为读写器的端口,这里赋值以后是1001
他们给的例子。是一个控件使用很简单了。