新中新二代身份证dll调用,报尝试读取或写入受保护的内存,这通常指示其他内存已损坏 这个错

wufato 2012-06-09 06:03:36
新中新二代身份证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);
就算是新中新光盘里给的示例程序我运行都是报这个错,在论坛里找半天也没找到确切的解决方法,求高手解决
...全文
987 26 打赏 收藏 转发到动态 举报
写回复
用AI写文章
26 条回复
切换为时间正序
请发表友善的回复…
发表回复
ynwrs 2012-08-23
  • 打赏
  • 举报
回复
25楼正解,如果是vista以上系统,调试中可能也会出现此错误,必须编译后用管理员模式运行。默认的普通是禁止访问系统根目录文件的。
tiandi_g 2012-07-03
  • 打赏
  • 举报
回复
sdk中有一个license.dat文件,把这个文件copy到系统盘根目录下就OK了!我试过的!
wufato 2012-06-10
  • 打赏
  • 举报
回复
明天就要交东西了,结贴算了,周一去用同事的电脑试试,谢谢大家
wufato 2012-06-10
  • 打赏
  • 举报
回复
谢谢大家,我是新中新光盘里给的例子运行都报错,而且是公司的笔记本,家里的电脑都报一样的错
足球中国 2012-06-10
  • 打赏
  • 举报
回复
新中新的有个示例。你问他们官方要一下。

我刚上传的好象新中新的。http://download.csdn.net/detail/zanfeng/4363831

http://download.csdn.net/detail/zanfeng/4363831
他们给的例子。是一个控件使用很简单了。
qldsrx 2012-06-10
  • 打赏
  • 举报
回复
表示关注,另外你有没有试过其它已有程序读取,确认读卡器已经身份证本身都可以正常被读取,这种和外设有个的操作,先要排除外设问题才行。
wufato 2012-06-10
  • 打赏
  • 举报
回复
嗯,也试了一下,之前返回2是因为第一个参数传的端口传错了,传入正确的端口以后,还是报错,
尝试读取或写入受保护的内存。这通常指示其他内存已损坏 这个错,
调用方法:
var p = Marshal.AllocHGlobal(10240);
var result = Syn_ReadMsg(nport, 0, p);
nport为读写器的端口,这里赋值以后是1001
足球中国 2012-06-10
  • 打赏
  • 举报
回复
可能与版本有关系。新中新的现在出了好几种设备。相同设备也不同版本了。我也遇到一回改为他们的控件方式。
__天涯寻梦 2012-06-09
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 的回复:]
不行,都是乱码,而且返回值还是2,表明没有调用成功,谢谢你了,我想想其它方法吧
[/Quote]
先把参数定义为 IntPtr 型是不想方法执行被可能错误的结构所影响,因为就算传对了结构,也是一片内存区域,与这无异,而传错了,方法就无法返回了。等把方法的其他部分调整好,能返回正确值了,再将类型设置为结构,解析结构内容。
wufato 2012-06-09
  • 打赏
  • 举报
回复
#pragma once
#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++里的原型应该是这个
WAN 2012-06-09
  • 打赏
  • 举报
回复
楼主你要贴出C++的结构定义以及函数声明大家才能进行详细的检查。你原来贴的代码从面上看应该是没什么问题的,除了这里:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
除非你的dll文档明确表明需要设置Pack,否则建议将其删除
还有,返回值2是什么意思?有没有可能是之前需要调用的初始化之类的函数没完成?
wufato 2012-06-09
  • 打赏
  • 举报
回复
不行,都是乱码,而且返回值还是2,表明没有调用成功,谢谢你了,我想想其它方法吧
__天涯寻梦 2012-06-09
  • 打赏
  • 举报
回复
nRet = Syn_ReadMsg(0, 0,ref p);
指针不要 ref ,不然就变成双重指针了,把 ref 修饰去掉,方法定义的地方也去掉,然后运行12楼的代码
wufato 2012-06-09
  • 打赏
  • 举报
回复
嗯,谢谢啊,没报错,不过其实上没正确读取身份证的信息,而且我是这样写的
var type = typeof(IDCardData);
var size = Marshal.SizeOf(type);
var p = Marshal.AllocHGlobal(size);

// 调用方法
nRet = Syn_ReadMsg(0, 0,ref p);
这里返回nRet返回值是0就表示正确返回了,但是返回值不是0,表示返回的值有问题
__天涯寻梦 2012-06-09
  • 打赏
  • 举报
回复
var p = Marshal.AllocHGlobal(10240);
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 有没哪个不是乱码
__天涯寻梦 2012-06-09
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 的回复:]
谢谢啊,二楼的方法试了可以,就是出来的乱码
[/Quote]
那好,把所有的 Marshal.PtrToStringAnsi 换成 Marshal.PtrToStringUni 试试还是不是乱码?
__天涯寻梦 2012-06-09
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 的回复:]
IntPtr p = Marshal.AllocHGlobal(10240);
var result = Syn_ReadMsg(0, 0,ref p);
这样调用不会出错,就是赋值进去不了
[/Quote]
“赋值进去不了”什么意思?
wufato 2012-06-09
  • 打赏
  • 举报
回复
谢谢啊,二楼的方法试了可以,就是出来的乱码
wufato 2012-06-09
  • 打赏
  • 举报
回复
IntPtr p = Marshal.AllocHGlobal(10240);
var result = Syn_ReadMsg(0, 0,ref p);
这样调用不会出错,就是赋值进去不了
__天涯寻梦 2012-06-09
  • 打赏
  • 举报
回复
极端点的方式
// 方法定义
[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);

这两行代码执行看看会不会报错
加载更多回复(6)

111,129

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Creator Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧