zoukankan      html  css  js  c++  java
  • C#程序开发范例_IC卡读写

    13.3  IC卡应用
    IC(Integrated Circuit)卡,也被称作智能卡(Smart Card),具有写入数据和存储数据的功能,IC卡内存储器的内容可以根据需要有条件地供外部读取,完成信息处理和判定。由于其内部具有集成电路,不但可以存储大量信息,具有极强的保密性能,并且还具有抗干扰、无磨损、寿命长等特性。因此在各个领域中得到广泛应用。下面通过两个实例介绍IC卡的简单应用。

    实例422 向IC卡中写入数据

    实例说明
    IC卡是携带应用信息和数据的媒体,空白IC卡是不能立即使用的,必须对IC卡应用系统进行初始化,写入系统IC卡和个人密码,个人专用信息和应用数据。下面介绍如何向IC卡中写入数据。运行本例,在“数据”文本框中输入要存入IC卡中的数据,单击“写数据”按钮,即可将输入的数据写入IC卡中。如图13.6所示。

    技术要点
    本例使用的是深圳明华生产的明华IC卡读写器,用户在使用时将驱动程序安装完毕后,即可正常使用本系统。

    本例通过调用Mwic_32.dll链接库,进行IC卡的读写工作。下面介绍与IC卡写操作相关的几个函数。

    (1)auto_init函数

    该函数用于初始化IC卡读卡器。语法如下:

    public static extern int auto_init(int port, int baud);

    参数说明如下。

    l     port:标识端口号,Com1对应的端口号为0;Com2对应的端口号为1,依此类推。

    l     baud:标识波特率。

    l     返回值:如果初始化成功,返回值是IC卡设备句柄;如果初始化失败,返回值小于零。

    (2)setsc_md函数

    该函数用于设置设备密码模式。语法如下:

    public static extern int setsc_md(int icdev, int mode);

    参数说明如下。

    l     icdev:标识设备句柄,通常是auto_init函数的返回值。

    l     mode:标识设备密码模式,如果为0,设备密码有效,设备在加电时必须验证设备密码才能对设备进行操作。如果为1,设备密码无效。

    l     返回值:如果函数执行成功返回值为零,否则小于零。

    (3)get_status函数

    该函数用于获取设备的当前状态。语法如下:

    public static extern Int16 get_status(int icdev, Int16* state);

    参数说明如下。

    l     icdev:标识设备句柄,通常是auto_init函数的返回值。

    l     state:用于接收函数返回的结果。如果为0表示读卡器中无卡,为1表示读卡器中有卡。

    l     返回值:如果函数执行成功返回值为零,否则小于零。

    (4)csc_4442函数

    该函数用于核对IC卡密码。语法如下:

    public static extern Int16 Csc_4442(int icdev, int len, [MarshalAs(UnmanagedType.LPArray)] byte[] p_string);

    参数说明如下。

    l     icdev:标识设备句柄,通常是auto_init函数的返回值。

    l     len:标识密码长度,其值为3。

    l     p_string:标识设置的密码。

    l     返回值:如果函数执行成功返回值为零,否则小于零。

    (5)swr_4442函数

    该函数用于向IC卡中写入数据。语法如下:

    public static extern int swr_4442(int icdev, int offset, int len, char* w_string);

    参数说明如下。

    l     icdev:标识设备句柄,通常是auto_init函数的返回值。

    l     offset:标识地址的偏移量,范围是0~255。

    l     len:标识字符串长度。

    l     w_string:标识写入的数据。

    (6)ic_exit函数

    该函数用于关闭设备端口。语法如下:

    public static extern int ic_exit(int icdev);

    参数说明如下。

    l     icdev:标识设备句柄,通常是auto_init函数的返回值。

    (7)dv_beep函数

    该函数使读卡器嗡鸣。语法如下:

    public static extern int dv_beep(int icdev, int time);

    参数说明如下。

    l     icdev:标识设备句柄,通常是auto_init函数的返回值。

    l     time:标识嗡鸣持续的时间,单位是10毫秒。

    实现过程
    (1)新建一个项目,命名为Ex13_05,默认窗体为Form1。

    (2)在Form1窗体中,主要添加两个Button控件,用于执行向卡中写入数据和退出程序的操作,添加一个TextBox控件,将TextBox中数据写入IC卡中。

    (3)主要程序代码。

    将程序所使用的操作IC卡的函数,封装在类IC中。代码如下:

    [StructLayout(LayoutKind.Sequential)]

    public unsafe class IC

    {

        //对设备进行初始化

        [DllImport("Mwic_32.dll", EntryPoint = "auto_init", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]

        public static extern int auto_init(int port, int baud);

        //设备密码格式

        [DllImport("Mwic_32.dll", EntryPoint = "setsc_md", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]

        public static extern int setsc_md(int icdev, int mode);

        //获取设备当前状态

        [DllImport("Mwic_32.dll", EntryPoint = "get_status", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]

        public static extern Int16 get_status(int icdev, Int16* state);

        //关闭设备通讯接口

        [DllImport("Mwic_32.dll", EntryPoint = "ic_exit", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]

        public static extern int ic_exit(int icdev);

        //使设备发出蜂鸣声

        [DllImport("Mwic_32.dll", EntryPoint = "dv_beep", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]

        public static extern int dv_beep(int icdev, int time);

        //向IC卡中写数据

        [DllImport("Mwic_32.dll", EntryPoint = "swr_4442", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]

        public static extern int swr_4442(int icdev, int offset, int len, char* w_string);

        //核对卡密码 

        [DllImport("Mwic_32.dll", EntryPoint = "csc_4442", SetLastError = true, CharSet = CharSet.Auto, ExactSpelling = true, CallingConvention = CallingConvention.Winapi)]

        public static extern Int16 Csc_4442(int icdev, int len, [MarshalAs(UnmanagedType.LPArray)] byte[] p_string);

    }

    下面代码主要用于将TextBox中数据写入到IC卡中。代码如下:

            private void button1_Click(object sender, EventArgs e)

            {

                //初始化

                int icdev = IC.auto_init(0, 9600);

                if (icdev < 0)

                    MessageBox.Show("端口初始化失败,请检查接口线是否连接正确。","错误提示",MessageBoxButtons.OK,MessageBoxIcon.Information);

                int md = IC.setsc_md(icdev, 1); //设备密码格式

                unsafe

                {

                    Int16 status = 0;

                    Int16 result = 0;

                    result = IC.get_status(icdev, &status);

                    if (result != 0)

                    {

                        MessageBox.Show("设备当前状态错误!");

                        int d1 = IC.ic_exit(icdev);   //关闭设备

                        return;

                    }

                    if (status != 1)

                    {

                        MessageBox.Show("请插入IC卡");

                        int d2 = IC.ic_exit(icdev);   //关闭设备

                        return;

                    }

                }

                unsafe

                {

                    //卡的密码默认为6个f(密码为:ffffff),1个f的16进制是15,两个f的16进制是255

                    byte[] pwd = new byte[3] { 255, 255, 255 };

                    //byte[] pwd = new byte[3] { 0xff, 0xff, 0xff };

                    //char[] pass=new ch{0xff,0xff,0xff};

                    Int16 checkIC_pwd = IC.Csc_4442(icdev, 3, pwd);

                    if (checkIC_pwd < 0)

                    {

                        MessageBox.Show("IC卡密码错误!");

                        return;

                    }

                    char str = 'a';

                    int write=-1;

                    for (int j = 0; j < textBox1.Text.Length; j++)

                    {

                        str = Convert.ToChar(textBox1.Text.Substring(j, 1));

                        write = IC.swr_4442(icdev, 33 + j, textBox1.Text.Length, &str);

                    }

                    if (write == 0)

                    {

                        int beep = IC.dv_beep(icdev, 20);  //发出蜂鸣声

                        MessageBox.Show("数据已成功写入IC卡中!");

                    }

                    else

                        MessageBox.Show("数据写入IC卡失败!");

                }

                int d = IC.ic_exit(icdev);  //关闭设备

            }

    举一反三
    根据本实例,读者可以实现以下功能。

      在图书借阅中使用IC卡。

      利用IC卡控制上网。

    实例423 读取IC卡中的数据

    实例说明
    向IC卡写入数据后,就可以进行读卡操作了。运行本例,将写入数据的IC卡插入读卡器,单击【读卡】按钮,IC卡中的数据将显示在文本框中。如图13.7所示。

    技术要点
    本例中主要调用srd_4442函数读取IC卡中的数据,相关函数介绍请参考实例“向IC卡中写入数据”中的“技术要点”部分。这里只介绍读卡函数。

    q srd_4442函数

    该函数用于读取IC卡中的数据。语法如下:

    public static extern int srd_4442(int icdev, int offset, int len, char* r_string);

    参数说明如下。

    l     icdev:标识设备句柄,通常是auto_init函数的返回值。

    l     offset:标识地址的偏移量,范围是0~255。

    l     len:标识字符串长度。

    l     r_string:用于存储返回的数据。

    实现过程
    (1)新建一个项目,命名为Ex13_06,默认窗体为Form1。

    (2)在Form1窗体中,主要添加两个Button控件,用于读取卡中的数据和退出程序,添加一个TextBox控件,显示卡中的数据。

    (3)主要程序代码。

            private void button1_Click(object sender, EventArgs e)

            {

                //初始化

                int icdev = IC.auto_init(0, 9600);

                if (icdev < 0)

                    MessageBox.Show("端口初始化失败,请检查接口线是否连接正确。", "错误提示", MessageBoxButtons.OK, MessageBoxIcon.Information);

                int md = IC.setsc_md(icdev, 1); //设备密码格式

                int i = IC.dv_beep(icdev, 10);  //发出蜂鸣声

                unsafe

                {

                    Int16 status = 0;

                    Int16 result = 0;

                    result = IC.get_status(icdev, &status);

                    if (result != 0)

                    {

                        MessageBox.Show("设备当前状态错误!");

                        int d1 = IC.ic_exit(icdev);   //关闭设备

                        return;

                    }

                    if (status != 1)

                    {

                        MessageBox.Show("请插入IC卡");

                        int d2 = IC.ic_exit(icdev);   //关闭设备

                        return;

                    }

                }

                unsafe

                {

                    char str = 'a';

                    int read = -1;

                    for (int j = 0; j < 6; j++)

                    {

                        read = IC.srd_4442(icdev, 33 + j, 1, &str);

                        textBox1.Text = textBox1.Text + Convert.ToString(str);

                    }

                    if (read == 0)

                        MessageBox.Show("IC卡中数据读取成功!");

                }

                int d = IC.ic_exit(icdev);  //关闭设备

            }

    举一反三
    根据本实例,读者可以开发以下程序。

      读取IC卡电话系统。

      公交车刷卡系统。

    实例424 利用IC卡制作考勤程序

    实例说明
    IC卡广泛应用于各行业,包括银行卡、公交车刷卡系统、读书卡等。下面介绍使用IC卡制作简单的公司考勤系统。运行本例,单击【刷卡】按钮,即可对员工进行考勤。实现效果如图13.8所示。

    技术要点
    有关IC卡的操作函数请参考实例“向IC卡中写入数据”和“读取IC卡中的数据”中的“技术要点”部分。

    下面主要介绍通过IC卡如何实现员工考勤。主要将写入IC卡中的卡号读取出来,然后从数据表中查询员工信息。具体代码请参考实现过程。

    实现过程
    (1)新建一个项目,命名为Ex13_07,默认窗体为Form1。

    (2)在Form1窗体中,主要添加5个TextBox控件和6个Label控件,用途如图13.7所示,添加一个Button控件,执行刷IC卡命令。

    (3)主要程序代码。

            private void button1_Click(object sender, EventArgs e)

            {

                //初始化

                int icdev = IC.auto_init(0, 9600);

                if (icdev < 0)

                    label6.Text = "端口初始化失败,请检查接口线是否连接正确。";

                unsafe

                {

                    Int16 status = -1;

                    Int16 result = IC.get_status(icdev, &status);

                    int md = IC.setsc_md(icdev, 1);   //设备密码格式

                    if (result < 0)

                    {

                        int d1 = IC.ic_exit(icdev);  //关闭设备

                        return;

                    }

                    else if ((result == 0) && (status == 0))

                    {

                        int d2 = IC.ic_exit(icdev);  //关闭设备

                        label6.Text = "请插入IC卡";

                        return;

                    }

                }

                unsafe

                {

                    char str = 'a';

                    int read = -1;

                    string ic = "";

                    for (int j = 0; j < 6; j++)

                    {

                        read = IC.srd_4442(icdev, 33 + j, 1, &str);

                        ic = ic + Convert.ToString(str);

                    }

                    textBox1.Text = ic;

                    if (read == 0)

                        label6.Text = "刷卡成功!";

                    int beep = IC.dv_beep(icdev, 20);  //发出蜂鸣声

                    int d3 = IC.ic_exit(icdev);   //关闭设备

                }

                int d = IC.ic_exit(icdev);  //关闭设备

                //根据卡号,查找相应数据

                OleDbConnection con = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + "price.mdb" + ";Persist Security Info=False");

                OleDbDataAdapter dap = new OleDbDataAdapter("select * from worker where ICID='"+textBox1.Text+"'", con);

                DataSet ds = new DataSet();

                dap.Fill(ds, "table");

                if (ds.Tables.Count > 0)

                {

                    textBox2.Text = ds.Tables[0].Rows[0][0].ToString();

                    textBox3.Text = ds.Tables[0].Rows[0][1].ToString();

                    textBox4.Text = ds.Tables[0].Rows[0][2].ToString();

                    textBox5.Text = ds.Tables[0].Rows[0][3].ToString();

                }

                else

                {

                    label6.Text = "不存在该用户!";

                }

            }

  • 相关阅读:
    解决SharePoint 文档库itemadded eventhandler导致的上传完成后,编辑页面保持报错的问题,错误信息为“该文档已经被编辑过 the file has been modified by...”
    解决SharePoint 2013 designer workflow 在发布的报错“负载平衡没有设置”The workflow files were saved but cannot be run.
    随机实例,随机值
    Spring4笔记
    struts2笔记(3)
    struts2笔记(2)
    获取文本的编码类型(from logparse)
    FileUtil(from logparser)
    DateUtil(SimpleDateFormat)
    struts2笔记
  • 原文地址:https://www.cnblogs.com/bingyun84/p/1498570.html
Copyright © 2011-2022 走看看