想实现这样的一个试用版的软件给用户体验,如果用户觉得满意的话,会索要激活码激活使用正式版,下面就讲笔者的一个实现方案,可以参考参考
关于能看懂的条件
- 会使用Visual Studio 开发工具
- 熟悉WinForm项目
- 首先,需要生成一个序列号,必须是设备唯一的ID,通过读取用户的PC设备硬件ID来组合生成,下面是
Hardware.cs
类的实现,获取硬件信息生成序列号,类似手机的IMEI
识别码
using System;
using System.Collections.Generic;
using System.Management;
using System.Text.RegularExpressions;
namespace WindowsFormsApp2.lib
{
/// <summary>
/// 硬件信息
/// </summary>
public class Hardware
{
//获取CPU序列号
public string GetCPUSerialNumber()
{
try
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher("Select * From Win32_Processor");
string sCPUSerialNumber = "";
foreach (ManagementObject mo in searcher.Get())
{
sCPUSerialNumber = mo["ProcessorId"].ToString().Trim();
break;
}
return sCPUSerialNumber;
}
catch
{
return "";
}
}
//获取主板序列号
public string GetBIOSSerialNumber()
{
try
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher("Select * From Win32_BIOS");
string sBIOSSerialNumber = "";
foreach (ManagementObject mo in searcher.Get())
{
sBIOSSerialNumber = mo.GetPropertyValue("SerialNumber").ToString().Trim();
break;
}
return sBIOSSerialNumber;
}
catch
{
return "";
}
}
//获取硬盘序列号
public string GetHardDiskSerialNumber()
{
try
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT * FROM Win32_PhysicalMedia");
string sHardDiskSerialNumber = "";
foreach (ManagementObject mo in searcher.Get())
{
sHardDiskSerialNumber = mo["SerialNumber"].ToString().Trim();
break;
}
return sHardDiskSerialNumber;
}
catch
{
return "";
}
}
/// <summary>
/// 获取序列号
/// </summary>
/// <returns></returns>
public String GetTheSerialNumber()
{
var h = this;
String res = h.GetBIOSSerialNumber() + " " + h.GetHardDiskSerialNumber() + " " + h.GetCPUSerialNumber();
res = Regex.Replace(res, @"[\s+\-\._\/]", "");
var res2 = "";
for(int i=0; i<res.Length; i++)
{
if (i >= 40) break;
if (i>0 && i % 4 == 0) res2 += "-";
res2 += res[i];
}
return res2.ToUpper();
}
/// <summary>
/// 转换处理,可以说成算法,自己编成独特的
/// </summary>
/// <param name="text"></param>
/// <returns></returns>
public String decode(String text)
{
//...具体实现过程需要自己编写
}
}
}
- 怎么写一个自己构造的独特算法呢,晒一下笔者的
decode()
方法实现,计算出激活码就可以跟用户输入的激活码来比对,无问题的话,就在用户的PC设备中存储好,提示用户已激活,需要重启就好
/// <summary>
/// 转换处理,可以说成算法,自己编成独特的
/// </summary>
/// <param name="text"></param>
/// <returns></returns>
public String decode(String text)
{
var lines = text.Split('-');
var nums = new List<int>();
for (int i = 0; i < lines.Length; i++)
{
var line = lines[i];
int num = 0;
for (int j = 0; j < line.Length; j++)
{
int n = 0;
switch (line[j])
{
case 'A':
case 'a':
n = 10;
break;
case 'B':
case 'b':
n = 11;
break;
case 'C':
case 'c':
n = 12;
break;
case 'D':
case 'd':
n = 13;
break;
case 'E':
case 'e':
n = 14;
break;
case 'F':
case 'f':
n = 15;
break;
case 'G':
case 'g':
n = 16;
break;
case 'H':
case 'h':
n = 17;
break;
case 'I':
case 'i':
n = 18;
break;
case 'J':
case 'j':
n = 19;
break;
case 'K':
case 'k':
n = 20;
break;
case 'L':
case 'l':
n = 21;
break;
case 'M':
case 'm':
n = 22;
break;
case 'N':
case 'n':
n = 23;
break;
case 'O':
case 'o':
n = 24;
break;
case 'P':
case 'p':
n = 25;
break;
case 'Q':
case 'q':
n = 26;
break;
case 'R':
case 'r':
n = 27;
break;
case 'S':
case 's':
n = 28;
break;
case 'T':
case 't':
n = 29;
break;
case 'U':
case 'u':
n = 30;
break;
case 'V':
case 'v':
n = 31;
break;
case 'W':
case 'w':
n = 32;
break;
case 'X':
case 'x':
n = 33;
break;
case 'Y':
case 'y':
n = 34;
break;
case 'Z':
case 'z':
n = 35;
break;
default:
int.TryParse(line[j].ToString(), out n);
break;
}
num += n;
if (j + 1 < line.Length) num += (int)Math.Pow(10, line.Length - j - 1);
}
nums.Add(num);
}
String res = "";
foreach (var num in nums)
{
var str = num.ToString();
if (res.Length > 0) res += "-";
res += str;
}
return res;
}
- 在程序启动的一个主窗口
Form1
逻辑中需要做一下处理,参考如下代码段,这样启动程序要先判断是否存在保存的激活码文件,如果存在,就执行算法比对文件中的激活码,对的话,就变成正式版,若不对的话,就是默认试用版,使用功能受限
namespace WindowsFormsApp2
{
/// <summary>
/// 启动主窗口
/// </summary>
public partial class Form1 : Form, CommonListener
{
public Form1()
{
InitializeComponent();
}
bool isActive = false;
//激活窗口
Form2 f = new Form2();
private void Form1_Load(object sender, EventArgs e)
{
//h 就是 Hardware 对象
var h = f.h;
//这里是使用激活窗口里的方法来获取用户设备序列号
f.serialNuber = h.GetTheSerialNumber();
//存有激活码的文件
var path = Form2.getKeyFilePath();
if (File.Exists(path))
{
var lines = File.ReadAllLines(path);
if (lines.Length > 0)
{
//激活码放在第一行了
var key = lines[0];
//判断是否跟计算得出激活码的一致
if (key == h.decode(f.serialNuber))
{
f.keyNuber = key;
//改为已激活状态
isActive = true;
if (lines.Length > 1)
{
//...这里可处理其它的
}
return;
}
}
}
Text += "(试用版)";
}
}
}
- 基本激活窗口
Form2
就只有三个组件,一个输入框为序列号并设为只读属性,另一个输入框由用户输入激活码,还有一个点击激活按钮
namespace WindowsFormsApp2
{
/// <summary>
/// 激活窗口
/// </summary>
public partial class Form2 : Form
{
public Hardware h = new Hardware();
public Form2()
{
InitializeComponent();
}
public String serialNuber = "";
public String keyNuber = "";
private void Form2_Load(object sender, EventArgs e)
{
//初始化显示
Text = "激活";
label1.Text = "序列号:";
label2.Text = "激活码:";
label3.Text = "激活后,系统使用无限制,请激活找******";
//判断序列号长度
if (serialNuber.Length>0)
{
textBox1.Text = serialNuber;
textBox1.ReadOnly = true;
}
//判断激活码长度
if (keyNuber.Length>0)
{
textBox2.Text = keyNuber;
textBox2.ReadOnly = true;
button1.Text = "已激活";
button1.Enabled = false;
}
else
{
button1.Text = "确定激活";
}
}
/// <summary>
/// 点击 确定激活 按钮
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button1_Click(object sender, EventArgs e)
{
//计算激活码
var resutl = h.decode(textBox1.Text);
//核对用户输入的激活码是否一致
if (textBox2.Text!=resutl)
{
MessageBox.Show("激活码不正确!", "激活失败!", MessageBoxButtons.OK, MessageBoxIcon.Warning);
Close();
return;
}
//激活成功,生成一个文件key.ini,写入激活码,下次启动就读取该文件验证是否可激活使用
var path = getKeyFilePath();
File.WriteAllText(path, resutl);
MessageBox.Show("写入在key.ini文件中,请保留它,关闭程序重新打开,可激活使用!", "激活成功!", MessageBoxButtons.OK, MessageBoxIcon.Information);
Close();
}
public static String getKeyFilePath()
{
return Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "key.ini");
}
}
}
- 激活的过程大致思路已实现,接下来讲讲激活工具窗口
Form3
,和上面的激活窗口Form2
看着一样,也许有读书会想:激活工具窗口 放在一起会不会不太合适呢,放心吧,目前这个窗口是隐藏的,具体怎么用,后面会讲
namespace WindowsFormsApp2
{
public partial class Form3 : Form
{
public Form3()
{
InitializeComponent();
}
private void Form3_Load(object sender, EventArgs e)
{
Text = "激活工具";
label1.Text = "序列号:";
label2.Text = "激活码:";
button1.Text = "激活";
}
/// <summary>
/// 点击激活
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button1_Click(object sender, EventArgs e)
{
var h = new Hardware();
textBox2.Text = h.decode(textBox1.Text);
}
}
}
- 在程序入口
Program
处, 添加一个判断,这里有加了小动作,不曾想尝试自己独立弄一个激活工具自己保管,结果那一天自己忙到想不起放哪里却找不到,或者不小心搞丢,那只能在桌上发呆😳,小动作自己拿到小本本记到,从此心里有个小秘密🤭
namespace WindowsFormsApp2
{
static class Program
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main(String[] args)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
//通过CMD窗口对程序输入命令,格式 WindowsFormsApp2 -activate bibibibibibi...
if (args.Length==2 && args[0]=="-activate" && args[1]=="bibibibibibi...")
{
//打开激活工具
Application.Run(new Form3());
}
else
{
//运行主程序
Application.Run(new Form1());
}
}
}
}