当前位置:编程学习 > C#/ASP.NET >>

被这个折腾快晕了!问了技术总监也没有解决的问题,C# 调用C++ dll出现问题,not supported Exception

C++ 原型函数:


IC卡读写操作
原型: int IccIsoCommand(int   slot, 
APDU_SEND  *ApduSend,
APDU_RESP  *ApduRecv,
unsigned char *Response,
 DWORD size
)
功能描述: 读写IC卡
输入参数: slot   卡头索引号
ApduSend   发送的数据,结构如下:
typedef struct 
{
unsigned char Command[4]; // 命令头
unsigned int Lc; // 要发送的数据长度
unsigned char *DataIn; // 要发送的数据缓冲
unsigned int Le; // 要接收的数据长度
} APDU_SEND;
输出参数: ApduRecv   接收的数据,结构如下:
typedef struct
{
unsigned int LenOut;
unsigned char *DataOut;
unsigned char SWA;
unsigned char SWB;
} APDU_RESP;
输出参数: unsigned char *Response, 实际数据加两个状态字;
输出参数: DWORD size , 数据长度加2(两个状态字).

返回值: 0 - 成功
1 - ERROR CARD
7 - ICCISOCOMMAND ERROR
8 - AUTO RESPONSE ERROR


C# 调用代码

声明:
[DllImport("SmartCard.dll", EntryPoint = "IccIsoCommand", SetLastError = true)]
        public static extern int IccIsoCommand(int slot,  ref APDU_SEND ApduSend, ref APDU_RESPU ApduRecv ,byte []response,uint size);


定义与C++对应的结构体及一个byte类型数组:

byte []BYTE1 = new byte[20];
        [StructLayout(LayoutKind.Sequential)]
        public struct APDU_SEND
        {
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
            public byte[] Command;
            [MarshalAs(UnmanagedType.U4 , SizeConst = 4)]
            public uint Lc;
            //[MarshalAs(UnmanagedType.LPArray)]
            public unsafe  byte *p;
             
            //public string DataIn;
            //public byte[] DataIn;//byte 数组指针
            //public StringBuilder DataIn;
            [MarshalAs(UnmanagedType.U4 , SizeConst = 4)]
            public uint Le;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct APDU_RESPU
        {
            [MarshalAs(UnmanagedType.U4 , SizeConst = 4)]
            public uint LenOut;
            //[MarshalAs(UnmanagedType.LPArray)]
            //public string DataOut;
            //public StringBuilder DataOut;
            //public byte[] DataOut;
            public unsafe   byte *p ;
            
            [MarshalAs(UnmanagedType.U1, SizeConst = 1)]
            public byte SWA;
            [MarshalAs(UnmanagedType.U1, SizeConst = 1)]
            public byte SWB;
        }

调用代码:
            APDU_SEND SS = new APDU_SEND();
            APDU_RESPU RR = new APDU_RESPU();

            SS.Command = new byte[4] { 0x00, 0xa4, 0x00, 0x00 };
           
            //SS.DataIn = "3f00";
            //IntPtr p = Marshal.AllocHGlobal(5);
            //Marshal.Copy(BYTE1 ,0,SS.p ,5);
            BYTE1[0] = 0X3f;
            BYTE1[1] = 0X00;
            unsafe 
            {

                fixed (byte* p = &BYTE1[0]) 
               {
                   //SS.p = 0Xff;
                   SS.p = p;
               }
            };
            SS.Le = 128;
            SS.Lc = 02;
            byte[] Response = new byte[10];
            
            try
            {
                int result = IccIsoCommand(2, ref  SS, ref RR, Response,130);
                MessageBox.Show("result = " + result);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }

为什么会出现not supported Exception这种异常抛出呢?所有DLL函数出现错误都是出现这种错误吗?我的程序错在哪里呢?有位技术比较好的朋友说C++ 接口定义不对,要改写,不知道是不是真的。请各位高手看看,最好能给你一个完整点代码啊
    --------------------编程问答-------------------- 删掉c++代码,解雇c++程序员。如果确实不需要c#来写,那么外包(哪怕给给人)并且要求按期完成就好了,由对方负责进行压力测试。 --------------------编程问答-------------------- 哪怕给给人  -->  哪怕包给个人 --------------------编程问答-------------------- IC卡读写操作不就是一个窜口操作,需要C++吗?? --------------------编程问答-------------------- C++程序如果是你们自行开发的,那么与上层C#交互,中间加一层C++/CLI的Wrap,不要用PInvoke,
不规范的结构体定义或导出函数参数定义,会造成很多莫名其妙的PInvoke问题.

另外直接在结构体里定义char*,实在不敢恭维 --------------------编程问答-------------------- 你的C++函数是stdcall吗?

另外结构中
//public byte[] DataIn;定义成数组更好一些。
关键是分配,我看你定义成指针,但是下面的分配不对吧。

做个桥:
如果实在不好解决,那就用VC再次对该函数进行封装,将他的参数精简或修改为C#方便调用的类型。
--------------------编程问答-------------------- 我觉的应该是参数类型的问题。 多换几个参数类型试。 --------------------编程问答-------------------- C++函数是另外一个公司提供的,不是我们弄的。不知道啊。
引用 5 楼 isjoe 的回复:
你的C++函数是stdcall吗?

另外结构中
//public byte[] DataIn;定义成数组更好一些。
关键是分配,我看你定义成指针,但是下面的分配不对吧。

做个桥:
如果实在不好解决,那就用VC再次对该函数进行封装,将他的参数精简或修改为C#方便调用的类型。
--------------------编程问答-------------------- public byte[] DataIn,我在C#里面定义可以吗?
C++里面定义的是 char * 类型,这样可以对应上吗?
期待你回答。
引用 5 楼 isjoe 的回复:
你的C++函数是stdcall吗?

另外结构中
//public byte[] DataIn;定义成数组更好一些。
关键是分配,我看你定义成指针,但是下面的分配不对吧。

做个桥:
如果实在不好解决,那就用VC再次对该函数进行封装,将他的参数精简或修改为C#方便调用的类型。
--------------------编程问答-------------------- 为什么是要删除C++ 代码啊?什么问题啊?大哥,不会开玩笑吧。请具体一点啊
引用 1 楼 sp1234 的回复:
删掉c++代码,解雇c++程序员。如果确实不需要c#来写,那么外包(哪怕给给人)并且要求按期完成就好了,由对方负责进行压力测试。
--------------------编程问答-------------------- 是在哪一行报的错,还是一调用就报错了? --------------------编程问答-------------------- 先用dumpbin -exports 检查dll里面IccIsoCommand方法是不是确实是IccIsoCommand名字; --------------------编程问答-------------------- 将c#中对应的struct中的字段修改如下:
我只改了struct APDU_SEND,你可以把其他也改了试试
[StructLayout(LayoutKind.Sequential)]
  public struct APDU_SEND
  {
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]//格式要求可以不用,除非c++中是宽字节
public string Command;
  
public int Lc;
  
public StringBuilder DataIn;//char*用StringBuilder对应
    
  //public string DataIn;
  //public byte[] DataIn;//byte 数组指针
  //public StringBuilder DataIn;
public int Le;
  }

c++   ----   c#  格式对应
char ---- string
int ----  int
char* ----StringBuilder
这几个对应我试过,如果c++中字符行有中文,要改成w_char,用StringBuilder对应 --------------------编程问答-------------------- IccIsoCommand里面会不会setlasterror?
不会的话把声明里的setlasterror=true去掉 --------------------编程问答-------------------- 看函数的返回值应该是没设置的了.
把SetLastError=true去掉后检查一下程序功能是否有异常.
没有的话应该没啥问题了 --------------------编程问答-------------------- 我一般都用C++/CLI来调 --------------------编程问答--------------------
引用 2 楼 sp1234 的回复:
哪怕给给人  -->  哪怕包给个人


我想问你你是来干啥的 说的你好牛逼一样 不来给楼主解决问题。。 --------------------编程问答-------------------- using System;
using System.Collections.Generic;
using System.Text;
using System.IO.Ports;
using System.Security.Cryptography;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading;

namespace MIF
{

    public class IMIF  
    {
        Mutex mut = new Mutex();
        void WaitOne(string Name )
        {
           // Console.WriteLine("{0} WaitOne+++++++++++++++++++++++++++++++++", Name );
            mut.WaitOne();
            
        }
        void ReleaseMutex(string Name)
        {
            mut.ReleaseMutex();
           // Console.WriteLine("{0} ReleaseMutex++++++++++++++++++++++++++++", Name);
        }



        #region IC卡相关枚举和常量
        public enum PICC
        {
            PICC_REQIDL = 0x26,
            PICC_REQALL = 0x52
        }
        public enum MIF
        {
            MIF_succeed, MIF_EexistCard, MIF_NoCard, MIF_EexistCardNONum
        }
        public enum MI
        {
            MI_OK = 0,
            MI_CHK_OK = 0,
            MI_CRC_ZERO = 0,
            MI_CRC_NOTZERO = 1,
            MI_NOTAGERR = -1,
            OpenErr = -1,
            MI_CHK_FAILED = -1,
            MI_CRCERR = -2,
            MI_CHK_COMPERR = -2,
            MI_EMPTY = -3,
            MI_AUTHERR = -4,
            MI_PARITYERR = -5,
            MI_CODEERR = -6,
            MI_SERNRERR = -8,
            MI_KEYERR = -9,
            MI_NOTAUTHERR = -10,
            MI_BITCOUNTERR = -11,
            MI_BYTECOUNTERR = -12,
            MI_IDLE = -13,
            MI_TRANSERR = -14,
            MI_WRITEERR = -15,
            MI_INCRERR = -16,
            MI_DECRERR = -17,
            MI_READERR = -18,
            MI_OVFLERR = -19,
            MI_POLLING = -20,
            MI_FRAMINGERR = -21,
            MI_ACCESSERR = -22,
            MI_UNKNOWN_COMMAND = -23,
            MI_COLLERR = -24,
            MI_RESETERR = -25,       /// 复位错误 IC 没有正确响应*/
            MI_INITERR = -25,
            MI_INTERFACEERR = -26,
            MI_ACCESSTIMEOUT = -27,
            MI_NOBITWISEANTICOLL = -28,
            MI_QUIT = -30,
            MI_RECBUF_OVERFLOW = -50,
            MI_SENDBYTENR = -51,
            MI_SENDBUF_OVERFLOW = -53,
            MI_BAUDRATE_NOT_SUPPORTED = -54,
            MI_SAME_BAUDRATE_REQUIRED = -55,
            MI_WRONG_PARAMETER_VALUE = -60
        }


        public enum USR
        {


            USR_Start1 = 0x55,//开始位第一位
            USR_Start2 = 0xAA,//开始位第二位
            USR_Request = 0x01,        /// 寻卡 防碰撞获得卡号*/
            USR_Select = 0x02,       /// 选择卡*/
            USR_PiccRead = 0x03,        /// 读卡*/
            USR_PiccWrite = 0x04,        /// 写卡*/
            USR_PiccHalt = 0x05,        /// 挂起*/
            USR_PcdRfReset = 0x06,        /// 复位M1 卡 + 时间(ms) =2*/
            USR_LoadKeyE2 = 0x10,        /// 下载密钥 到E2 存储器 可掉电存储*/
            USR_PiccAuthE2 = 0x11,        /// 从E2 验证密钥*/
            USR_BuzzSwitch = 0x30,        /// 蜂鸣器开关1=on 0=off*/
            USR_LoadKeyTMP = 0x50,        /// 下载临时key    类似USR_LoadKeyE2 */
            USR_Switch_KEY = 0x62,       /// 切换KEY 类似USR_BuzzSwitch*/
            KeyCommandLen = 0x9
        }
        public enum Secteur
        {


            Secteur0 = 0x00, //第一扇区
            Secteur1 = 0x01, //第一扇区
            Secteur2 = 0x02, //第一扇区
            Secteur3 = 0x03, //第一扇区
            PICC_AUTHENT1A = 0x60,
            PICC_AUTHENT1B = 0x61,
            KEYA = 0x60,
        }




        //抛出消息的定义
        public enum DriverMsg
        {
            /// <summary>
            ///有卡
            /// </summary>
            ExistCard = 1201,
            /// <summary>
            /// 无卡
            /// </summary>
            NotExistCard = 1202,
            /// <summary>
            /// 读写器正常
            /// </summary>
            ReaderNormal = 1941,
            /// <summary>
            /// 读写器异常
            /// </summary>
            ReaderError = 1942,
        }


        //ETC宏定义

        public const int CmdLengthSelectSAM = 0x02;
        public const int CmdTypeSelectSAM = 0x80;
        public const int CmdLengthSAMReset = 0x01;
        public const int CmdSAMReset = 0x82;
        public const int CmdLengthGetCardType = 0x02;
        public const int CmdGet_CardType = 0x01;


        //ETC错误码定义
        public enum ETCError
        {
            NO_ERROR = 1,//NO ERROR
            PARAM1_ERROR = -1,//THE 1ST PARAMETER IS WRONG
            PARAM2_ERROR = -2,//THE 2ST PARAMETER IS WRONG
            PARAM3_ERROR = -3,//THE 3ST PARAMETER IS WRONG
            PARAM4_ERROR = -4,//THE 4ST PARAMETER IS WRONG
            PARAM5_ERROR = -5,//THE 5ST PARAMETER IS WRONG
            PORT_NOT_EXIST = -6,//PORT NOT EXIST
            PORT_NOT_OPENED = -7,//PORT NOT OPENED
            PORT_ALREADY_OPENED = -8,//PORT ALREADY OPENED
            PORT_ALREADY_CLOSED = -9,//PORT ALREADY CLOSED
            RX_TIMEOUT_ERROR = -10,//TIMEOUT WHILE RECEIVING DATA
            TX_TIMEOUT_ERROR = -11,//TIMEOUT WHILE TRANSMITTING DATA

            FRAME_ERROR = -20,//UNKONWN FRAME TYPE
            CRC_ERROR = -21,//CRC ERROR
            COMMUNICATION_ERROR = -22,//COMMUNICATION ERROR
            READER_NOT_FOUND = -23,//CANNOT FIND READER
            AUTHENTICATION_ERROR = -24,//AUTHENTICATION ERROR
            SEQUENCE_ERROR = -25,//TXSEQ CANNOT MATCH WITH RXSEQ

            PICC_NOTAGGERR = -101,//ERROR ON PICC:NO IC CARD IN THE RANGE OF ANTENNA
            PICC_CRCERR = -102,//ERROR ON PICC:CRC16 CHECK ERROR
            PICC_AUTHERR = -103,//ERROR ON PICC:FAILURE ON AUTHENTICATION
            PICC_PARITYERR = -104,//ERROR ON PICC:PARITY CHECK ERROR
            PICC_CODEERR = -105,//ERROR ON PICC:COMMAND ERROR
            PICC_SERNRERR = -106,//ERROR ON PICC:INVALID CARD SERIAL NUMBER
            PICC_KEYERR = -107,//ERROR ON PICC:INVALID KEY
            PICC_NOTAUTHERR = -108,//ERROR ON PICC:INVALID OPERATION
            PICC_BITCOUNTERR = -109,//ERROR ON PICC:UNKOWN FRAME FROM PICC
            PICC_BYTECOUNTERR = -110,//ERROR ON PICC:UNKOWN FRAME FROM PICC
            PICC_FRAMEINGERR = -111,//ERROR ON PICC:UNKOWN FRAME FROM PICC
            PICC_UNKNOWN_COMMAND = -112,//ERROR ON PICC:UNVALID ICC COMMAND
            PICC_COLLERR = -113,//ERROR ON PICC:COLLISION HAPPENED
            PICC_ACCESSTIMEOUT = -114,//ERROR ON PICC:TIMEOUT ON OPERATION
            PICC_NOT_IMPLEMENTED = -115,//ERROR ON PICC:COMMAND NOT EXECUTED
            PICC_WRONG_VALUE = -116,//ERROR ON PICC:INVALID PARAMETER
            PICC_VALERR = -117,//ERROR ON PICC:INVALID VALUE ON ELECTRONIC PURSE OPERATION
            PICC_WRITEERR = -118,//ERROR ON PICC:ERROR ON WRITE CARD
            PICC_OVFLERR = -119,//ERROR ON PICC:READ BUFFER OVERFLOW

            PSAM_TIMEOUTERR = -161,//ERROR ON PSAM:TIMEOUT ON OPERATION
            PSAM_CODE_ERR = -162,//ERROR ON PSAM:INVALID PARAMETER
            PSAM_CRCERR = -163,//ERROR ON PSAM:CRC CHECK ERROR

            PCD_OUTOFBUFFER = -181,//ERROR ON READER:READER BUFFER OVERFLOW
            PCD_PCCOMMERR = -182,//ERROR ON READER:COMMUNICATION ERROR

        }

        //错误代码定义
        public enum ErrorType
        {

            /// <summary>
            /// 没有错误
            /// </summary>
            NoError = 0,
            /// <summary>
            /// 打开读写器错误
            /// </summary>
            Error_OpenReader = 1,
            /// <summary>
            /// 关闭读写器错误
            /// </summary>
            Error_CloseReader = 2,
            /// <summary>
            /// 输入的参数长度错误
            /// </summary>
            Error_ParamLength = 3,
            /// <summary>
            /// 更新0015文件失败
            /// </summary>
            Error_Update0015_Failed = 4,
            /// <summary>
            /// 执行Pro卡命令失败,返回值不是0x2328
            /// </summary>
            Error_ExcuteProCmd = 5,
            /// <summary>
            /// 取随机数失败
            /// </summary>
            Error_GetRand_Failed = 6,
            /// <summary>
            /// 选择1001目录失败
            /// </summary>
            Error_Select1001_Failed = 7,
            /// <summary>
            /// 打开卡片失败
            /// </summary>
            Error_OpenCard = 8,
            /// <summary>
            /// 执行COS命令错
            /// </summary>
            Error_ExcuteCosCmd = 9,
            /// <summary>
            /// 关闭卡片失败
            /// </summary>
            Error_CloseCard = 10,
            /// <summary>
            /// 读0015文件失败
            /// </summary>
            Error_Read0015_Failed = 11,
            /// <summary>
            /// 读余额失败
            /// </summary>
            Error_ReadBalance = 12,
            /// <summary>
            /// 获取终端机编号错
            /// </summary>

            Error_GetTerminalNo = 13,
            /// <summary>
            /// 充值失败
            /// </summary>
            Error_IncreaseMoney = 14,
            /// <summary>
            /// Sam卡复位失败
            /// </summary>
            Error_SamReset = 15,
            /// <summary>
            /// 选择DF01失败
            /// </summary>
            Error_SelectSamDF01 = 16,
            /// <summary>
            /// 扣款失败
            /// </summary>
            Error_DecreaseMoney = 17,
            /// <summary>
            /// 计算MAC1错误
            /// </summary>
            Error_Mac1 = 18,
            /// <summary>
            /// 校验MAC2错误
            /// </summary>
            Error_VerifyMac2 = 19
        }
  
--------------------编程问答--------------------       public const int CommandRequestLength = 0x02;
        public const int CommandReadLength = 0x04;
        public const int CommandSelecLength = 0x05;
        public const int CommandWriteLength = 0x14;
        public const int CommandBuzzSwitchLength = 0x14;
        public const int CRC8 = 0x80;
        #endregion
        bool _IsComReady = false;
        public bool IsComReady
        {
            get { return _IsComReady; }
            set { _IsComReady = value; }
        }
        protected static SerialPort sp = null;
        public bool Open(string comname)
        {
            if (sp == null)
            {
                sp = new SerialPort(comname, 115200);
                sp.ReadTimeout = 2000;
            }
            if (!sp.IsOpen)
            {
                sp.Open();

            }
            IsComReady = sp.IsOpen;
            return sp.IsOpen;
        }
        /// <summary>
        /// 关闭和释放串口
        /// </summary>
        public void Close()
        {
            if (sp != null)
            {
                if (sp.IsOpen)
                {
                    sp.Close();

                }
                sp.Dispose();

            }
        }

        public byte[] Hex2Bin(string hexstr)
        {

            byte[] bin = new byte[hexstr.Length / 2];
            for (int i = 0; i < hexstr.Length / 2; i++)
            {
                bin[i] = (byte)int.Parse(hexstr.Substring(i * 2, 2), System.Globalization.NumberStyles.AllowHexSpecifier);
            }
            return bin;
        }
        public byte[] Hex2Bin(string hexstr, ref byte[] bin)
        {
            for (int i = 0; i < hexstr.Length / 2; i++)
            {
                bin[i] = (byte)int.Parse(hexstr.Substring(i * 2, 2), System.Globalization.NumberStyles.AllowHexSpecifier);
            }
            return bin;
        }
        public string Bin2Hex(byte[] bin)
        {
            return Bin2Hex(bin, bin.Length);
        }
        public string Bin2Hex(byte[] bin, int Len)
        {
            string result = "";
            byte[] hb = bin;
            for (int i = 0; i < Len; i++)
            {
                result += hb[i].ToString("X2");
            }
            return result.Trim();
        }

        byte[] TempCommand = new byte[1000];
        public byte[] SendCommand(string Command, ref int Len)
        {

            return SendCommand(Hex2Bin(Command), ref Len);
            // Hex2Bin(Command, ref TempCommand);
            // return SendCommand(TempCommand, Command.Length / 2, ref Len);
        }
        public byte[] SendCommand(byte[] buffer, ref int Len)
        {
            return SendCommand(buffer, buffer.Length, ref Len);
        }
        /// <summary>
        /// 发送指令并返回返回值
        /// </summary>
        /// <param name="comname">端口名称</param>
        /// <param name="buffer"></param>
        /// <returns></returns>
        byte[] rb = new byte[4096];
        byte[] result = new byte[1000];
        int SendTotal = 0;
        int ReadTotal = 0;
        public byte[] SendCommand(byte[] buffer, int bufferLen, ref int Len)
        {

            sp.DiscardInBuffer();
            sp.DiscardOutBuffer();
            SendTotal += bufferLen;
            Console.WriteLine("Send :{0}", SendTotal.ToString());
            sp.Write(buffer, 0, bufferLen);
            System.Threading.Thread.Sleep(10);
            Len = 0;
            int l = 0;
            do
            {
                l = sp.Read(rb, 0, 4096);
                Array.Copy(rb, 0, result, Len, l);
                Len += l;
                System.Threading.Thread.Sleep(10);
            } while (sp.BytesToRead > 0);
            ReadTotal += Len;
            Console.WriteLine("Read :{0}", ReadTotal.ToString());
            return result;
        }
      

 
        public bool ResetPro()
        {
            int Len = 0;            
            string rex = Bin2Hex(SendCommand("55aa02060A",ref Len),Len);           
            return rex.EndsWith("00");
        }
      
        byte[] CardNubmerTemp = new byte[50];
        public string  GetCardNumber()
        {
           string CardNubmer =  null;
           WaitOne("GetCardNumber");
           if( ResetPro())
           {
               CardNubmer = RequestPro();

               if (null != CardNubmer)
               {
                   string cn = "";
                   for (int i = 0; i < 3; i++)
                   {
                       cn += CardNubmer.Substring((2 - i) * 2, 2);  
                   }

                   int k = int.Parse(cn, System.Globalization.NumberStyles.HexNumber);
                   CardNubmer = k.ToString();          
               }
           }
           ReleaseMutex("GetCardNumber");
           return CardNubmer;
        }
        /// <summary>
        /// 请求Pro卡。 
        /// </summary>
        /// <returns>如果有卡, 返回后四位,如果没卡, 返回null</returns>
        public string RequestPro()
        {
            string result = null;
            int Len = 0;

            string rex = Bin2Hex(SendCommand("55AA020152", ref Len), Len);
            if (rex != "" )
            {
                result = rex.Substring(rex.Length - 2 * 4, 2 * 4);
            }
            return result;
        }
 
    }
} --------------------编程问答-------------------- ===========================下面是执行智能卡的指令。。。

 /// <summary>
        /// 最终进行执行CPU命令
        /// </summary>
        /// <param name="command">字节之间允许带有空格,则会在第一行就被替换掉</param>
        /// <returns></returns>
        public  byte[] ExcCPUCmd(string command,ref int Len)
        {
          
            //sprintf(chTemp, "%02X%02X%02X%02X%02X%02X%02X%02X%02X%s", USR_Start1, USR_Start2, strlen(command) / 2 + 6, 0x90
            //, strlen(command) / 2 + 4, 0x01, 0x06, 0x0a, 0x00, command);
            command = command.Replace(" ", "");
            string hexcmd = string.Format("{0:X2}{1:X2}{2:X2}{3:X2}{4:X2}{5:X2}{6:X2}{7:X2}{8:X2}{9}",
                 (int)USR.USR_Start1, (int)USR.USR_Start2, command.Replace(" ", "").Length / 2 + 6, 0x90
                 , command.Replace(" ", "").Length / 2 + 4, 0x01, 0x06, (cmdstate ? 0x0a : 0x0b), 0x00, command);
            //(cmdstate ? 0x0a:0x0b) 奇数此是0a ,偶数次是 0b 
            //Console.WriteLine("ExcCPUCmd SendCommand:{0}", hexcmd);
            byte[] b = SendCommand(hexcmd, ref Len);
            cmdstate = !cmdstate;
            //Console.WriteLine("ExcCPUCmd SendCommand:{0}", Bin2Hex(b));
            return b;
        }
        
        /// <summary>
        /// 执行CPU指令
        /// </summary>
        /// <param name="command">命令内容</param>
        /// <param name="strResponse">返回值</param>
        /// <param name="strSW12">执行情况,9000表示成功</param>
        /// <returns>通过判断strSW12是否为9000来判断此处的返回值</returns>
     
        
        public  CPUResult CPU_CommandEx(string command)
        {    
CPUResult result = new CPUResult();
            COMMAND = command;
            Console.WriteLine("CPU_CommandEx :{0}", COMMAND);
            int Len = 0;
            string strTemp = Bin2Hex(ExcCPUCmd(command,ref Len),Len);            
            //Console.WriteLine("CPU_CommandEx Read :{0}", strTemp);

            if ("" != strTemp)
            {
                if (strTemp.StartsWith("55AA01"))
                {
                    if (strTemp != "55AA010")
                    {
                        //如果这里成立, 则说明这条命令在读卡器至卡中间出现故障,卡片可能没有接受此命令。 
                        //如有必要请参考ISO14444 在本程序中isready如果为false时, 则需要重新请求卡片-选卡-请求ATS
                        //isready = false;
                        result.RADResult = false;
                    }
                    else
                    {
                        result.RADResult = true;
                    }
                }
                else //返回大于一个字节, 返回值无论如何,至少是俩字节。 
                {

                   byte[]   RetLen =  Hex2Bin(strTemp.Substring(4, 2));
                    if (RetLen.Length >= 1)
                    {
                        int rlen = RetLen[0];//返回字节长度
                        if (rlen > 1)
                        {
                            result.RADResult = true;
                            result.PROSW12 = strTemp.Substring(strTemp.Length - 8, 4);
                            int tt = strTemp.Length;
                            result.PROResult = result.PROSW12 == "9000";//握奇 的成功返回值为 9000 
                            SW12 = result.PROSW12;
                            Console.WriteLine("CPU_CommandEx PROSW12: " + SW12);
                            result.PROResponse = strTemp.Substring(0, strTemp.Length - 8).Substring(6 + 6);//回馈值  
                        }
                    }
                }


            }
            return result;//卡片命令是否执行成功
        } --------------------编程问答-------------------- 但是我要填充到结构体里面的指令是16进制的,怎么填充到这个结构体里面呢?我的QQ是191970570 ,欢迎大家赐教我。
引用 12 楼 toto_2000061 的回复:
将c#中对应的struct中的字段修改如下:
我只改了struct APDU_SEND,你可以把其他也改了试试
[StructLayout(LayoutKind.Sequential)]
  public struct APDU_SEND
  {
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]//格式要求可以不用,除非c++中是……
--------------------编程问答-------------------- 我QQ 191970570,欢迎大家加我。I AM WOMAN --------------------编程问答-------------------- 19楼猛男啊 --------------------编程问答-------------------- 21楼原来是女的。
这个年头碰到个女程序mm真不容易呀。
 int IccIsoCommand(int slot,  
APDU_SEND *ApduSend,
APDU_RESP *ApduRecv,
unsigned char *Response,
 DWORD size
)

int IccIsoCommand(int slot, byte[] ApduSend, byte[] ApduRecv, byte[]Response, int size);
不用管什么结构体,就用这个试试,看行不行。
以前写了一段时间的IC卡读写命令,开始真的很烦。
写习惯了就好了。
直接使用byte数组写入就行。只要把数据组织好就OK了。
每次ApduSend的长度是可以预知的,你计算命令及内容长度结果。
ApduRecv 和 Response是不固定的。因为不知道会给你传回什么数据。
可以定义的大一些。如果你能估计到最大值的话就好了。反正现在电脑也不缺那点内存。
定义个几M都行的。 --------------------编程问答-------------------- unsigned char *Response, 

C#调用时,输出用ref unit  试试看? --------------------编程问答-------------------- 或者StringBuilder  输出,记得声明长度 --------------------编程问答-------------------- 请你加一下我QQ啊,191970570

引用 23 楼 mjp1234airen4385 的回复:
21楼原来是女的。
这个年头碰到个女程序mm真不容易呀。
 int IccIsoCommand(int slot,  
APDU_SEND *ApduSend,
APDU_RESP *ApduRecv,
unsigned char *Response,
 DWORD size
)

int IccIsoCommand(int slot, byte[] ApduSend, byt……
--------------------编程问答-------------------- 貌似是要使用com组件来调用。之前做过税控打印的第三方c++的dll,也是用c#来调用

你们的总奸的确是淫才,老牛逼了,膜拜中。

最后小小鄙视下  --------------------编程问答--------------------
int IccIsoCommand(int slot, byte[] ApduSend, byte[] ApduRecv, byte[]Response, int size);
你这个是否是声明呀?调用的时对应的 byte[]调用啊,但是定义的时结构体啊,意思是对byte[]数组里面的数组分别赋值吗?请你加我QQ啊
引用 23 楼 mjp1234airen4385 的回复:
21楼原来是女的。
这个年头碰到个女程序mm真不容易呀。
 int IccIsoCommand(int slot,  
APDU_SEND *ApduSend,
APDU_RESP *ApduRecv,
unsigned char *Response,
 DWORD size
)

int IccIsoCommand(int slot, byte[] ApduSend, byt……
--------------------编程问答-------------------- 给你点资料。。。C++和C#类型对照


http://topic.csdn.net/u/20090225/15/a6bc50ad-9721-4749-b189-dc4a4bc045a1.html
http://zhidao.baidu.com/question/90145938.html


LPSTR     char*     System.String 或 System.Text.StringBuilder    用 ANSI 修饰。
LPCSTR     Const char*     System.String 或 System.Text.StringBuilder    用 ANSI 修饰。
LPWSTR     wchar_t*     System.String 或 System.Text.StringBuilder    用 Unicode 修饰。
LPCWSTR     Const wchar_t*     System.String 或 System.Text.StringBuilder    用 Unicode 修饰。
FLOAT     Float     System.Single     32 位
DOUBLE     Double     System.Double     64 位


CHAR* 可以先实例化一个StringBuilder然后可以传给char*类型 
关于其他的请参考msdn中的c++与c#的类型转换 
对应关系如下: 
C++ ---- C# 
传入的char*  ----string 
传出的char* ---- StringBuilder(预分配空间) 
short  ----short 
char ---- byte 
char[n] ---- fixed byte[n] 
结构指针  ----结构指针 
函数指针 ---- 委托 

C++ C#
=====================================
WORD ushort
DWORD uint
UCHAR int/byte 大部分情况都可以使用int代替,而如果需要严格对齐的话则应该用bytebyte  
UCHAR* string/IntPtr
unsigned char* [MarshalAs(UnmanagedType.LPArray)]byte[]/?(Intptr)
char* string
LPCTSTR string
LPTSTR [MarshalAs(UnmanagedType.LPTStr)] string
long int
ulong uint
Handle IntPtr
HWND IntPtr
void* IntPtr
int int
int* ref int
*int IntPtr
unsigned int uint
COLORREF uint  

 


API与C#的数据类型对应关系表  
API数据类型 类型描述 C#类型 API数据类型 类型描述 C#类型  
WORD 16位无符号整数 ushort CHAR 字符 char  
LONG 32位无符号整数 int DWORDLONG 64位长整数 long  
DWORD 32位无符号整数 uint HDC 设备描述表句柄 int  
HANDLE 句柄,32位整数 int HGDIOBJ GDI对象句柄 int  
UINT 32位无符号整数 uint HINSTANCE 实例句柄 int  
BOOL 32位布尔型整数 bool HWM 窗口句柄 int  
LPSTR 指向字符的32位指针 string HPARAM 32位消息参数 int  
LPCSTR 指向常字符的32位指针 String LPARAM 32位消息参数 int  
BYTE 字节 byte WPARAM 32位消息参数 int  
--------------------编程问答-------------------- lz你把SetLastError=true去掉试过了吗? --------------------编程问答-------------------- C++ 中unsigned int Le 
int值比较小,还可以用byte表示,但是int取值超出byte类型了范围以后怎么骂?用byte数组能够表示int取值吗?
你的意思是不定义结构体吗?直接用byte 数组表示里面的数据吗?

我是用我朋友的账号发的


引用 23 楼 mjp1234airen4385 的回复:
21楼原来是女的。
这个年头碰到个女程序mm真不容易呀。
 int IccIsoCommand(int slot,  
APDU_SEND *ApduSend,
APDU_RESP *ApduRecv,
unsigned char *Response,
 DWORD size
)

int IccIsoCommand(int slot, byte[] ApduSend, byte……
--------------------编程问答-------------------- 试了不管用的啊
引用 30 楼 chrisak 的回复:
lz你把SetLastError=true去掉试过了吗?
--------------------编程问答-------------------- 你能帮我试试吗?请问,我的QQ 191970570,请加我。
引用 6 楼 lovesongforever 的回复:
我觉的应该是参数类型的问题。 多换几个参数类型试。
--------------------编程问答-------------------- 把byte数组中元素按C++ 函数中的赋值给参数吗?
比如 byte[0]到byte[3]赋值给slot,byte[4]到byte[多少]赋值给C++ 结构体ApduSend 对应的变量吗?这个要考虑结构体的对齐问题吗?

还有,我发送给程序的指令是16进制的字节流,但是在C++中,成员变量不一样,如何解决数据类型转换的问题呢?

引用 23 楼 mjp1234airen4385 的回复:
21楼原来是女的。
这个年头碰到个女程序mm真不容易呀。
 int IccIsoCommand(int slot,  
APDU_SEND *ApduSend,
APDU_RESP *ApduRecv,
unsigned char *Response,
 DWORD size
)

int IccIsoCommand(int slot, byte[] ApduSend, byt……
--------------------编程问答-------------------- 参考:http://blog.csdn.net/wo65432519/article/details/6542205 --------------------编程问答--------------------
引用 22 楼 stubborn_cow 的回复:
19楼猛男啊

+
补充:.NET技术 ,  C#
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,