新中新二代身份证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);
  就算是新中新光盘里给的示例程序我运行都是报这个错,在论坛里找半天也没找到确切的解决方法,求高手解决
                    

解决方案 »

  1.   

    方法第三个参数类型改为 IntPtr
    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 有没值
      

  2.   

    再不行就这样
    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);
      

  3.   

    谢谢回复,试了一下,不行,报未处理的“System.ExecutionEngineException”类型的异常出现在 未知模块 中这个错了
      

  4.   

    这个函数的功能,是提供前面2个参数,返回一个IDCardData结构的内容吧?
      

  5.   

    嗯,是的,[DllImport("SynIDCardAPI.dll", EntryPoint = "Syn_ReadMsg", CharSet = CharSet.Ansi)]
      public static extern int Syn_ReadMsg(int iPortID, int iIfOpen, ref IDCardData pIDCardData);
    这个是照抄sdk里的,sdk里的例子运行都是一样的错
      

  6.   

    2楼的方法执行过了吗?
    Syn_ReadMsg( ,  , p);
    这行能不能执行过去?
    如果不能,有没有 C/C++ 的函数和结构原型?
      

  7.   

    极端点的方式
    // 方法定义
    [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);这两行代码执行看看会不会报错
      

  8.   

     IntPtr p = Marshal.AllocHGlobal(10240);
    var result = Syn_ReadMsg(0, 0,ref p);
    这样调用不会出错,就是赋值进去不了
      

  9.   

    那好,把所有的 Marshal.PtrToStringAnsi 换成 Marshal.PtrToStringUni 试试还是不是乱码?
      

  10.   

    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 有没哪个不是乱码
      

  11.   

    嗯,谢谢啊,没报错,不过其实上没正确读取身份证的信息,而且我是这样写的
      var type = typeof(IDCardData);
    var size = Marshal.SizeOf(type);
    var p = Marshal.AllocHGlobal(size);// 调用方法
    nRet = Syn_ReadMsg(0, 0,ref p);
    这里返回nRet返回值是0就表示正确返回了,但是返回值不是0,表示返回的值有问题
      

  12.   

    nRet = Syn_ReadMsg(0, 0,ref p);
    指针不要 ref ,不然就变成双重指针了,把 ref 修饰去掉,方法定义的地方也去掉,然后运行12楼的代码
      

  13.   

    楼主你要贴出C++的结构定义以及函数声明大家才能进行详细的检查。你原来贴的代码从面上看应该是没什么问题的,除了这里:
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
    除非你的dll文档明确表明需要设置Pack,否则建议将其删除
    还有,返回值2是什么意思?有没有可能是之前需要调用的初始化之类的函数没完成?
      

  14.   

    #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++里的原型应该是这个
      

  15.   

    先把参数定义为 IntPtr 型是不想方法执行被可能错误的结构所影响,因为就算传对了结构,也是一片内存区域,与这无异,而传错了,方法就无法返回了。等把方法的其他部分调整好,能返回正确值了,再将类型设置为结构,解析结构内容。
      

  16.   

    嗯,也试了一下,之前返回2是因为第一个参数传的端口传错了,传入正确的端口以后,还是报错,
    尝试读取或写入受保护的内存。这通常指示其他内存已损坏 这个错,
    调用方法:
    var p = Marshal.AllocHGlobal(10240);
    var result = Syn_ReadMsg(nport, 0, p);
    nport为读写器的端口,这里赋值以后是1001
      

  17.   

    新中新的有个示例。你问他们官方要一下。我刚上传的好象新中新的。http://download.csdn.net/detail/zanfeng/4363831http://download.csdn.net/detail/zanfeng/4363831
    他们给的例子。是一个控件使用很简单了。
      

  18.   

    sdk中有一个license.dat文件,把这个文件copy到系统盘根目录下就OK了!我试过的!
      

  19.   

    25楼正解,如果是vista以上系统,调试中可能也会出现此错误,必须编译后用管理员模式运行。默认的普通是禁止访问系统根目录文件的。