Posted on 2012-11-13 10:21 星星之火116 阅读(3260) 评论(4) 编辑 收藏

我们在安装一些桌面应用程序的时候,往往在会有提示当前用户使用的是试用版,要进行注册。刚好最近做了一个关于应用程序注册的小demo(这里只是一个思路),在这里和大家分享一下。

项目的要求是这样的:

1. 能获取主机硬盘序列号、网卡MAC地址、CPU编号,并按照一定的算法由此生成机器码

2. 能根据机器码按照一定的算法生成注册码

3. 未注册时,不能使用会员管理功能

好的废话不多说,马上进入正题。还是一步一步通过示例向大家演示是如何实现的。

一、首先新建一个Winform应用程序,分别新建三个Form窗体分别为:Form1(登录),Register(注册)、Form2(主窗体)

界面布局分别如下:

二、首先,获得主机硬盘序列号、网卡MAC地址、CPU编号,并按照一定的算法由此生成机器码,然后再根据机器码生成注册码。(为了方便大家的使用,在这里我已经将其封装为一个类,并导出了类模板点击下载RegisterNumber.zip

该类中有一下的方法

1、GetMac()//获取网卡的MAC地址

2、GetHD()//获取硬盘的序列号

3、GetCPU()//获取CPU编号

4、GetMachineNumber()//根据已经获得的MAC地址、硬盘序列号、CPU编号,组合生成机器码

5、GetRegisterNumber()//根据生成的机器码生成注册码

以上所说的方法在该RegisterNumber类中均有具体的声明实现,有需要的朋友请自己下载使用,这里就不再做具体的讲解了,里边有很清楚的解释。

三、下面先要在Form1也就是登录窗体的Form_Load事件里做如下处理:

private void Form1_Load(object sender, EventArgs e)
        {
            skinEngine1.SkinFile = "WarmColor1.ssk";//为皮肤控件加载文件
            RegistryKey rk = Registry.LocalMachine.OpenSubKey("SOFTWARE");//打开系统的注册表项,Registry.LocalMachine包含本地计算机的配置数据。该字段读取 Windows 注册表基项 HKEY_LOCAL_MACHINE,OpenSubKey("SOFTWARE")表示打开本地计算机配置数据下SOFTWARE子项
            if (rk.GetValue("ZCM") != null)//获取程序的注册码的值,如果已经注册则有值,此时注册按钮隐藏,未注册时,值为null,此时显示注册按钮
            {
                btnzc.Visible = false;
            }
        }

注册按钮事件处理函数如下:

private void btnzc_Click(object sender, EventArgs e)
        {
            Register r = new Register();//显示注册窗体,进行注册
            r.Show();
        }

登录按钮事件处理函数如下:

private void button1_Click(object sender, EventArgs e)
        {
            this.DialogResult = DialogResult.OK;//这里只是一个demo所以只要用户点击登录就可以登录成功,这里只是将DialogResult的值设为OK,并没有直接显示Form2主窗体,因为在登录成功后,Form1登录窗体也就没有用了,所以程序在运行的时候,主线程并非Form1而是From2,因此还需要在Program.cs文件里进行设置。
        }

在Program.cs文件里设置如下:

static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
           <span style=""> Form1 f1 = new Form1();
            if (f1.ShowDialog() == DialogResult.OK)//表示当f1的DialogResult等于Ok时主程序才开始运行,所以在Form1中登录成功时要将Dialogresult设为OK
            {
                Application.Run(new Form2());
            }
</span>        }

四、这时如果要进行注册的话,我们就来看一下注册窗体(Register)里边的代码

1、首先看Register_Load事件里的方法

private void Register_Load(object sender, EventArgs e)
       {
           txtzcm.Text = RegisterNumber.GetRegisterNumber();//调用RegisterNumber的获取注册码的静态方法,获取当前机器的注册码,并未文本框赋值       
    //FileStream fs = new FileStream(Application.StartupPath + "\\zcm.txt", FileMode.Create, FileAccess.Write);//将注册码写入程序启动项的路径中zcm.txt文件中
           //StreamWriter sw = new StreamWriter(fs, Encoding.Default);
           //sw.Write(txtzcm.Text);
           //sw.Close();
           //fs.Close();
       }

2、然后看注册按钮里的处理事件

private void button1_Click(object sender, EventArgs e)
       {
           if (!string.IsNullOrEmpty(txtsr.Text))//先检测用户输入是否为空
           {
               if (txtsr.Text == txtzcm.Text)//再检测用户输入是否和显示的注册码一直
               {
                   RegistryKey rk = Registry.LocalMachine.OpenSubKey("SOFTWARE",true);
                   rk.SetValue("ZCM", txtsr.Text);//将注册码写入系统的关于程序信息的注册表下SOFTWARE文件下的"ZCM"名中
                   MessageBox.Show("注册成功!请再次登录!");
               }
               else
               {
                   MessageBox.Show("您输入的注册码不正确,请再次输入!");
               }
           }
           else
           {
               MessageBox.Show("请输入注册码!");
           }
       }

五、下面就进入最关键的一部分了,不论用户是否注册,都可以让用户进入程序的主界面,但是如果用户未注册则判断其使用次数是否超过限定的试用次数,如果超过则不能使用,反之则仍可继续试用,并在每次使用时提醒用户剩余试用次数,如果已经注册,则可以获得所有的权限功能。下面看具体的代码实现

private void Form2_Load(object sender, EventArgs e)
        {
            RegistryKey rk = Registry.LocalMachine.OpenSubKey("SOFTWARE",true);
            if (rk.GetValue("ZCM") != null)//读取系统的注册码,如果已注册则值值不为空可以使用,并标识已注册,反之则未注册
            {
                this.Text = "已注册";
                return;
            }
            this.Text = "试用版(未注册)";
            int count = (int)rk.GetValue("Count", 0);//未注册时获取用户试用的次数,如果是首次使用则赋值为0
            MessageBox.Show("感谢你已经使用了" + count + "次,请先注册再使用!");
            tabc.Visible = false;//因为是使用版,所以有很多 功能无法使用,这里演示将tabControl的visible属性设置为false来演示这种效果
            if (count < 30)//默认试用次数为30次,小于30次时仍可试用,反之则直接结束运行
                {
                    rk.SetValue("Count", count + 1);//需要更新注册表中用来记录登录次数的值,每试用一次,该值就增加一,等大于等于30时,程序试用结束,直接退出
                    count = 30 - count;
                    MessageBox.Show("您试用的是试用版!还有" + count + "次试用机会,请先注册再使用!");   
                }
                else
                {
                    MessageBox.Show("不好意思,请已经超出试用次数!请注册后再使用!");
                    Application.Exit();
                }
        }

好了,到这里程序的注册模块的设计和实现已经完成了,我们已经基本上可以实现了一个简单的程序注册,这里主要用到了Registry类和RegistryKey类用来保存系统的注册码、登录次数,下面我会向大家介绍下这两个类。RegistryKey位于Microsoft.Win32命名空间下。

注册表项是注册表中的基本组织单位,相当于Windows资源管理器中的文件夹。每个具体的注册表项都可以有子项,只要用户具有相应的权限,且注册表项不是基项或基项的下一级项,就可以删除该注册表项。每个注册表项也可带有与其相关联的多个值,它们用于存储信息,通常情况下我们可以创建一个RegistryKey(HKEY_LOCAL_MACHINE\Software)来保存有关计算机上安装的应用程序的信息,就比如我们在本例中就是这样使用来保存用户试用的次数以及机器的注册码。下面是几种常用主键:

HKEY_CLASSES_ROOT该主键包含了文件的扩展名和应用程序的关联信息以及Window Shell和OLE用于储存注册表的信息。该主键下的子键决定了在WINDOWS中如何显示该类文件以及他们的图标,该主键是从HKEY_LCCAL_MACHINE\SOFTWARE\Classes映射过来的。

HKEY_CURRENT_USER该主键包含了如用户窗口信息,桌面设置等当前用户的信息。 

HKEY_LOCAL_MACHINE主键包含了计算机软件和硬件的安装和配置信息,

该信息可供所有用户使用HKEY_USERS该主键记录了当前用户的设置信息,每次用户登入系统时,就会在该主键下生成一个与用户登入名一样的子键,该子键保存了当前用户的桌面设置、背景位图、快捷键,字体等信息。一般应用程序不直接访问改主键,而是通过主键HKEY_CURRENT_USER进行访问。

HKEY_CURRENT_CONFIG该主键保存了计算机当前硬件的配置信息,这些配置可以根据当前所连接的网络类型或硬件驱动软件安装的改变而改变

程序中为了读取指定主键下面的子键和子键中拥有的键值,主要使用了RegistryKey类中的四个方法:OpenSubKey,GetSubKeyNames,GetValueNames,GetValue。具体的用法和意思如下:OpenSubKey ( string name )方法主要是打开指定的子键。GetSubKeyNames ( )方法是获得主键下面的所有子键的名称,它的返回值是一个字符串数组。GetValueNames ( )方法是获得当前子键中的所有的键名称,它的返回值也是一个字符串数组。GetValue ( string name )方法是指定键的键值。

我们在该示例中都有用到这些方法,下面分别为大家演示:

需要声明一下的是为了方便使用,Registry类提供了7个公共的静态域,分别代表7个基本主键分别是:Registry.ClassesRoot,Registry.CurrentUser,Registry.LocalMachine,Registry.Users,Registry.CurrentConfig这里我们以Registry.LocalMachine

来做演示。

RegistryKey rk=Registry.LocalMachine.OpenSubKey("SOFTWARE",true");//这里有两个参数,第一个参数即要打开的文件夹,第二参数为为其指定写的权限
RegistryKey rk1=rk.CreateSubKey("Hello",RegistryKeyPermissionCheck.ReadWriteSubTree);//在SOFTWARE下创建子项,Hello,第二参数为枚举类型即允许对其读写
rk.SetValue("Count",0);//在SOFTWARE下设置键值对,保存登录次数
rk.GetValue("Count",0);//获取Count值,如果当前键值对不存在,则默认为0
rk.DeleteValue("Count");//删除值名称为"Count"的键值对
rk.DeleteSubKey("Hello");//删除SOFTWARE下的子项Hello

有细心的朋友可能会发现上边在Register(注册窗体)的Load事件中还有一些注释的代码如下:

FileStream fs = new FileStream(Application.StartupPath + "\\zcm.txt", FileMode.Create, FileAccess.Write);
           StreamWriter sw = new StreamWriter(fs, Encoding.Default);
           sw.Write(txtzcm.Text);
           sw.Close();
           fs.Close();

这段代码的作用是将注册码写入应用程序可执行文件路径下的zcm.txt文件中,这也是一个用来检测用户是否注册的思路,在用户进行注册的时候将注册码写入文本文件中,在登录的时候以打开或者新建的方式从文件中读取注册码,如果已经注册,则可读取到注册码,如果未注册,则显示未注册,并提示用户注册。

这里只是提供一个思路,希望能给大家带来一些帮助,还请大家多多指点。

WinForm应用程序之注册模块的设计与实现的更多相关文章

  1. winform 发布应用程序 提示 “未能注册模块(程序路径)\ieframe.dll”

    程序安装的时候出现未能注册模块(程序路径)\ieframe.dll提示 这种情况的出现,是因为引用的shdocvw.dll,目前发现了一个折中的解决方法,在安装程序里面,可以看到ieframe.dll ...

  2. 在WinForm应用程序中快速实现多语言的处理(2)--开发框架模块的整合

    我在上篇随笔<在WinForm应用程序中快速实现多语言的处理>里面介绍了Winform开发中多语言的处理解决方案,整个多语言解决方案是以实际需求为驱动,以减少代码改动,高效处理为目的,通过 ...

  3. C#/WPF/WinForm/.NET程序代码实现软件程序开机自动启动的两种常用方法的示例与源码下载带详细注释-源码代码-注册表方式-启动目录快捷方式

    C#/WPF/WinForm/.NET程序代码实现软件程序开机自动启动的两种常用方法的示例与源码下载带详细注释-源码代码-注册表方式-启动目录快捷方式 C#实现自动启动的方法-两种方法 源码下载地址: ...

  4. visual studio 设计第一个WinForm小程序

    WinForm小程序之消息框 首先打开visual studio 软件,然后[文件]-[新建]-[项目]-[Visual C#]-[Windows],选择Windows窗体应用程序,根据自己的需要修改 ...

  5. 在WinForm应用程序中快速实现多语言的处理

    在国际化环境下,越来越多的程序需要做多语言版本,以适应各种业务需求的变化.在Winform应用程序中实现多语言也有常规的处理方式处理,不过需要针对每个语言版本,重新修改Winform界面的显示,对一些 ...

  6. iOS开发一个用户登录注册模块需要解决的坑

    最近和另外一位同事负责公司登录和用户中心模块的开发工作,开发周期计划两周,减去和产品和接口的协调时间,再减去由于原型图和接口的问题,导致强迫症纠结症状高发,情绪不稳定耗费的时间,能在两周基本完成也算是 ...

  7. PHP+jQuery 注册模块开发

    /* ******* 环境: Apache2.2.8 + PHP5.2.6 + MySQL5.0.51b + jQuery-1.8.3.min.js ************** 其他组件:Zend_ ...

  8. Java入门:用户登录与注册模块1(实践项目)——分析

    任务描述:用户登录与注册是大多数软件都拥有的一个模块.请编写一个控制台程序,实现用户的登录与注册功能,并且用户能够修改自己信息. [需求分析]由于本程序是一个演示程序,用户的信息我们做简化处理,仅包括 ...

  9. Java SSH框架系列:用户登录模块的设计与实现思路

    1.简介用户登录模块,指的是根据用户输入的用户名和密码,对用户的身份进行验证等.如果用户没有登录,用户就无法访问其他的一些jsp页面,甚至是action都不能访问.二.简单设计及实现本程序是基于Jav ...

随机推荐

  1. 我的android学习经历29

    四大组件之广播接收者BroadcastReceiver 新建广播接收器 需要新建一个类继承类BroadcastReceiver,并且重写其中的方法onReceive(),不要在这个方法中添加过多的逻辑 ...

  2. Fragment 与 Fragment 相互传值

    方法: 1 接口回调 2 用一个单例类 3 bundle 4 获取fragment实例 , setter getter 传值

  3. CodeForces 496B Secret Combination

    Secret Combination Time Limit:2000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u ...

  4. DirectX 3d 取景变换

    在世界坐标系中,几何体和摄像机都是相对于世界坐标系定义的.但是当摄像机的位置和朝向任意时,投影变换及其它类型的变的就略显困难或效率不高.为了简化运算,我们将摄像机变的至世界坐标系原点,并将其旋转,使摄 ...

  5. Hibernate实体类注解

    常用的hibernate annotation标签如下: @Entity --注释声明该类为持久类.将一个Javabean类声明为一 个实体的数据库表映射类,最好实现序列化.此时,默认情况下,所有的类 ...

  6. NPO与X7R、X5R、Y5V、Z5U神马的有啥区别

    主要是介质材料不同.不同介质种类由于它的主要极化类型不一样,其对电场变化的响应速度和极化率亦不一样. 在相同的体积下的容量就不同,随之带来的电容器的介质损耗.容量稳定性等也就不同.介质材料划按容量的温 ...

  7. py延迟注入SQL脚本

    延迟注入工具(python) #!/usr/bin/env python # -*- coding: utf-8 -*- # 延迟注入工具 import urllib2 import time imp ...

  8. Shared Assembilies and Strongly Named Assemblies

    the .NET Framework has in place to deal with versioning problems. Two Kinds of Assemblies, Two Kinds ...

  9. GitHub上不错的Android开源项目(二)

    收集相关系列资料,自己用作参考,练习和实践.小伙伴们,总有一天,你也能写出 Niubility 的 Android App :-) 系列文章如下: GitHub上不错的Android开源项目(一):h ...

  10. ACDC

    acdc dcdc电源模块中大功率一般都是开关电源模式的,所以一般输入都是一个较宽的电源范围,体积也相对于变压器要小一些,效率高一些,但是纹波会偏大一些,如何选择就要看电路的需求来选择相应的方案