C#实现限制软件的使用次数

实例说明
为了使软件能被更广泛的推广,开发商希望能有更多的用户使用软件,但他们又不想让用户长时间免费使用未经授权的软件,这时就可以推出试用版软件,限制用户的使用次数,当用户感觉使用方便的话,可以花钱获取注册码,以获取其正式版软件。本实例使用C#实现了限制软件使用次数功能,运行本实例,如果程序未注册,则提示用户已经使用过几次,如图1所示,然后进入程序主窗体,单击主窗体中的“注册”按钮,弹出如图2所示的软件注册窗体,该窗体中自动获取机器码,用户输入正确的注册码之后,单击“注册”按钮,即可成功注册程序,注册之后的程序将不再提示软件试用次数。
    
图1  使用次数提示                       

图2  软件注册
注册码可由光盘中程序文件夹下提供的注册机程序得到。
设计思路
限制软件的使用次数时,首先需要判断软件是否已经注册,如果已经注册,则用户可以任意使用软件。如果软件未注册,则判断软件是否初次使用,如果是初次使用,则在系统注册表中新建一个子项,用来存储软件的使用次数,并且设置初始值为1;如果不是初次使用,则从存储软件使用次数的注册表项中获取已经使用的次数,然后将获取的使用次数加一,作为新的软件使用次数,存储到注册表中。
 技术要点
本实例获取软件使用次数时用到Registry类的GetValue方法,向注册表中写入软件使用次数时用到Registry类的SetValue方法。另外,在对软件进行注册时,需要根据硬盘序列号和CPU序列号生成机器码和注册码,此时用到WMI管理对象中的ManagementClass类、ManagementObject类和ManagementObjectCollection类,下面对本实例中用到的关键技术进行详细讲解。
(1)Registry类的GetValue方法
Registry类提供表示Windows注册表中的根项的RegistryKey对象,并提供访问项/值对的静态方法,其GetValue方法用来检索与指定的注册表项中的指定名称关联的值,如果在指定的项中未找到该名称,则返回提供的默认值;如果指定的项不存在,则返回null。GetValue方法语法格式如下:
public static Object GetValue(string keyName,string valueName,Object defaultValue)
?  keyName:以有效注册表根(如“HKEY_CURRENT_USER”)开头键的完整注册表路径。
?  valueName:名称/值对的名称。
?  defaultValue:当name不存在时返回的值。
?  返回值:如果由keyName指定的子项不存在,则返回null;否则,返回与valueName关联的值;或者,如果未找到valueName,则返回defaultValue。
例如,下面代码用来获取软件的使用次数:
tLong = (Int32)Registry.GetValue("HKEY_LOCAL_MACHINE/SOFTWARE/tryTimes", "UseTimes", 0);
Registry类位于Microsoft.Win32命名空间下。
(2)Registry类的SetValue方法
Registry类的SetValue方法用来设置注册表项中的名称/值对的值,该方法为可重载方法,它有两种重载形式,第一种重载形式语法格式如下:
public static void SetValue(string keyName,string valueName,Object value)
?  keyName:以有效注册表根(如“HKEY_CURRENT_USER”)开头键的完整注册表路径。
?  valueName:名称/值对的名称。
?  value:要存储的值。
第二种重载形式语法格式如下:
public static void SetValue(string keyName,string valueName,Object value,RegistryValueKind valueKind)
?  keyName:以有效注册表根(如“HKEY_CURRENT_USER”)开头键的完整注册表路径。
?  valueName:名称/值对的名称。
?  value:要存储的值。
?  valueKind:存储数据时使用的注册表数据类型。
例如,本实例中将软件使用次数写入注册表的实现代码如下:
if (tLong < 30)
{
    int Times = tLong + 1;
    Registry.SetValue("HKEY_LOCAL_MACHINE/SOFTWARE/tryTimes", "UseTimes", Times);
}
(3)ManagementClass类
ManagementClass类表示公共信息模型(CIM)管理类。管理类是一个WMI类,如Win32_LogicalDisk类和Win32_Process类,前者表示磁盘驱动器,后者表示进程(如Notepad.exe)。通过该类的成员,可以使用特定的WMI类路径访问WMI数据。
例如,本实例中使用ManagementClass类对本地进程信息进行访问,代码如下:
ManagementClass myCpu = new ManagementClass("win32_Processor");
(4)ManagementObject类
ManagementObject类表示WMI实例,本实例中用到该类的Get方法、GetPropertyValue方法和Properties属性,其中Get方法用来将WMI类信息绑定到管理对象,其语法格式如下:
public void Get()
GetPropertyValue方法用来获取某属性值的等效访问器,其语法格式如下:
public Object GetPropertyValue(string propertyName)
?  propertyName:相关的属性的名称。
? 返回值:指定的属性的值。
例如,本实例中获取硬盘序列号的代码如下:
ManagementObject disk = new ManagementObject("win32_logicaldisk.deviceid="d:"");
disk.Get();
return disk.GetPropertyValue("VolumeSerialNumber").ToString();
Properties属性用来获取描述管理对象属性的PropertyData对象的集合,其语法格式如下:
public virtual PropertyDataCollection Properties { get; }
? 属性值:返回一个PropertyDataCollection,它包含管理对象的属性。
例如,本实例中获取CPU序列号的代码如下:
foreach (ManagementObject myObject in myCpuConnection)
{
   strCpu = myObject.Properties["Processorid"].Value.ToString();
   break;
}
(5)ManagementObjectCollection类
ManagementObjectCollection类表示通过WMI检索到的管理对象的不同集合,此集合中的对象为从ManagementBaseObject派生的类型,包括ManagementObject和ManagementClass。
例如,本实例中通过使用ManagementClass对象的GetInstances方法获取管理对象集合,代码如下:
ManagementObjectCollection myCpuConnection = myCpu.GetInstances();
ManagementClass类、ManagementObject类和ManagementObjectCollection类都位于System.Management命名空间下,添加该命名空间时,首先需要在“添加引用”中添加System.Management.dll组件。
 实现过程
(1)新建一个Windows应用程序,将其命名为LimitSoftUseTimes,将其默认窗体重命名为frmMain。
(2)在 LimitSoftUseTimes项目中添加一个Windows窗体,命名为frmRegister,用来实现软件注册功能。frmRegister窗体主要用到的控件及说明如表1所示。
表1 frmRegister窗体主要用到的控件及说明

(3)主要程序代码。
frmMain窗体加载时,首先判断程序是否注册,如果已经注册,则将主窗体Text属性设置为“主窗体(已注册)”,否则,将主窗体Text属性设置为“主窗体(未注册)”,并且提示软件为试用版和已经使用的次数,同时将注册表中记录的软件使用次数加一。frmMain窗体的Load事件代码如下:
private void frmMain_Load(object sender, EventArgs e)
{
    RegistryKey retkey = Microsoft.Win32.Registry.LocalMachine.OpenSubKey("software", true).CreateSubKey("mrwxk").CreateSubKey("mrwxk.ini");    //打开注册表项
    foreach (string strRNum in retkey.GetSubKeyNames())  //判断是否注册
    {
        if (strRNum == softreg.getRNum())     //判断注册码是否相同
        {
            this.Text = "主窗体(已注册)";
            button1.Enabled = false;
            return;
        }
    }
    this.Text = "主窗体(未注册)";
    button1.Enabled = true;
    MessageBox.Show("您现在使用的是试用版,该软件可以免费试用30次!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
    Int32 tLong;
    try
    {
        //获取软件的已经使用次数
        tLong = (Int32)Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\tryTimes", "UseTimes", 0);
        MessageBox.Show("感谢您已使用了" + tLong + "次", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
    }
    catch
    {
        //首次使用软件
        Registry.SetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\tryTimes", "UseTimes", 0, RegistryValueKind.DWord);
        MessageBox.Show("欢迎新用户使用本软件", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
    }
    //获取软件已经使用次数
    tLong = (Int32)Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\tryTimes", "UseTimes", 0);
    if (tLong < 30)
    {
        int Times = tLong + 1;       //计算软件本次是第几次使用
        //将软件使用次数写入注册表
        Registry.SetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\tryTimes", "UseTimes", Times);
    }
    else
    {
        MessageBox.Show("试用次数已到", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
        Application.Exit();        //退出应用程序
    }
}
上面的代码中用到getRNum方法,该方法用来根据指定的机器码生成注册码,实现代码如下:
//生成注册码
public string getRNum()
{
    setIntCode();         //初始化127位数组
    for (int i = 1; i < Charcode.Length; i++)     //把机器码存入数组中
    {
        Charcode[i] = Convert.ToChar(this.getMNum().Substring(i - 1, 1));
    }
    for (int j = 1; j < intNumber.Length; j++)     //把字符的ASCII值存入一个整数组中。
    {
        intNumber[j] = intCode[Convert.ToInt32(Charcode[j])] + Convert.ToInt32(Charcode[j]);
    }
    string strAsciiName = "";       //用于存储注册码
    for (int j = 1; j < intNumber.Length; j++)
    {
        if (intNumber[j] >= 48 && intNumber[j] <= 57)  //判断字符ASCII值是否0-9之间
        {
            strAsciiName += Convert.ToChar(intNumber[j]).ToString();
        }
        else if (intNumber[j] >= 65 && intNumber[j] <= 90)  //判断字符ASCII值是否A-Z之间
        {
            strAsciiName += Convert.ToChar(intNumber[j]).ToString();
        }
        else if (intNumber[j] >= 97 && intNumber[j] <= 122) //判断字符ASCII值是否a-z之间
        {
            strAsciiName += Convert.ToChar(intNumber[j]).ToString();
        }
        else          //判断字符ASCII值不在以上范围内
        {
            if (intNumber[j] > 122)      //判断字符ASCII值是否大于z
            {
                strAsciiName += Convert.ToChar(intNumber[j] - 10).ToString();
            }
            else
            {
                strAsciiName += Convert.ToChar(intNumber[j] - 9).ToString();
            }
        }
    }
    return strAsciiName;        //返回生成的注册码
}
在frmMain窗体中单击“注册”按钮时,弹出“软件注册”窗体,该窗体加载时自动获得本机机器码,实现代码如下:
private void frmRegister_Load(object sender, EventArgs e)
{
   textBox1.Text = softreg.getMNum();
}
上面的代码中用到getMNum方法,该方法为自定义的返回值类型为string类型的方法,它主要用来根据本机的CPU和硬盘序列号生成本机机器码。getMNum方法实现代码如下:
//生成机器码
public string getMNum()
{
    string strNum = getCpu() + GetDiskVolumeSerialNumber(); //获得24位Cpu和硬盘序列号
    string strMNum = strNum.Substring(0, 24);    //从生成的字符串中取出前24个字符做为机器码
    return strMNum;         //返回生成的机器码
}
getMNum方法中用到getCpu和GetDiskVolumeSerialNumber两个自定义方法,其中getCpu方法用来获取本机CPU序列号,GetDiskVolumeSerialNumber方法用来获取本机硬盘序列号,它们的实现代码如下:
//获得CPU的序列号
public string getCpu()
{
    string strCpu = null;
    ManagementClass myCpu = new ManagementClass("win32_Processor");  //获取系统CPU处理器
    ManagementObjectCollection myCpuConnection = myCpu.GetInstances();
    foreach (ManagementObject myObject in myCpuConnection)
    {
        strCpu = myObject.Properties["Processorid"].Value.ToString();   //获取CPU序列号
        break;
    }
    return strCpu;
}
// 取得设备硬盘的序列号
public string GetDiskVolumeSerialNumber()
{
    //获取系统硬盘
    ManagementClass mc = new ManagementClass("Win32_NetworkAdapterConfiguration");
    ManagementObject disk = new ManagementObject("win32_logicaldisk.deviceid="d:"");
    disk.Get();
    return disk.GetPropertyValue("VolumeSerialNumber").ToString();   //返回硬盘序列号
}
frmRegister窗体中单击“注册”按钮时,程序首先判断是否输入注册码,如果没有,弹出信息提示,否则判断用户输入的注册码与本机应该生成的注册码是否相同,如果相同,则注册成功,并将软件注册信息写入到注册表中。“注册”按钮的Click事件代码如下:
private void button1_Click(object sender, EventArgs e)
{
    if (textBox2.Text == "")           //判断是否输入了注册码
    {
        MessageBox.Show("注册码输入不能为空!", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
    }
    else
    {
        if (textBox2.Text.Equals(softreg.getRNum()))      //判断注册码是否正确
        {
            RegistryKey retkey = Microsoft.Win32.Registry.LocalMachine.OpenSubKey("software", true).CreateSubKey("mrwxk").CreateSubKey("mrwxk.ini").CreateSubKey(textBox2.Text);  //打开注册表项,并创建一个子项
            retkey.SetValue("UserName", "mrsoft");      //为新创建的注册表项设置值
            MessageBox.Show("注册成功,程序需要重新加载!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
            this.Hide();           //隐藏当前窗体
            frmMain frmmain = new frmMain()       //实例化主窗体对象;
            frmmain.Show();          //显示主窗体
        }
        else
        {
            MessageBox.Show("注册码输入错误!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
    }
}
 

                                                                                                     ——摘自《C#编程词典》

  • 2
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值