开发者们经常需要为应用程序生成独特的序列号,以确保软件的合法使用。一种流行的方法是根据硬件资源码创建序列号。众所周知,每个硬件资源都有其独特的序列号,例如网络接口卡(NIC)、硬盘驱动器(HDD)等。本文将尝试基于硬盘驱动器的硬件码创建一个三部分的序列号。应用程序包括三个部分:1. 获取请求码;2. 根据硬盘硬件码生成序列号;3. 确认序列号和请求码与硬盘硬件码的一致性。
如上所述,代码分为三个部分:
1. 生成请求码。请求码基于硬盘硬件码创建。这里有一个简单的方法可以返回硬盘硬件码,该方法使用了System.Management命名空间中的ManagementObjectSearcher类。
private string GetHDDSerialNumber() {
string outs = "";
ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM Win32_DiskDrive");
foreach (ManagementObject queryObj in searcher.Get()) {
string a = queryObj["PNPDeviceID"].ToString();
if (a.Substring(0, 3) != "USB") {
outs = (queryObj["PNPDeviceID"]).ToString();
}
}
string s = "";
foreach (char t in outs) {
int i;
if (int.TryParse(t.ToString(), out i)) {
s += t.ToString();
}
}
return s;
}
ManagementObjectSearcher是检索管理信息的常用入口点之一。例如,它可以用来枚举系统上的所有磁盘驱动器、网络适配器、进程等管理对象,或者查询所有处于活动状态的网络连接、暂停的服务等。
因此,当用户点击获取请求码按钮时,按钮的事件处理程序会从GetHDDSerialNumber方法获取硬盘码,并将其转换为Base64字符串。
在常见场景中,客户或用户在安装后创建一个请求码,并通过Web或电子邮件等方式发送给应用程序所有者。应用程序所有者将返回一个基于请求码创建的序列号。
本示例的第二部分是生成一个基于请求码的唯一序列号。所有序列号都需要两个主要因素:1. 一个种子(这里种子是硬盘硬件码);2. 基于该种子创建序列号的算法。
好的,当点击生成序列号按钮时,处理程序会读取文本框中的请求,并将其转换为double。
byte[] requestCodeByte = Convert.FromBase64String(txtRequestCode.Text);
string requestCode = string.Empty;
foreach (byte b in requestCodeByte) {
requestCode += b.ToString();
}
long requestCodeDouble = Convert.ToInt64(requestCode);
在这个示例中,使用了三个简单的数学函数来创建一个三部分的序列号。可以使用自己的算法来创建自己的序列号。
long p1 = requestCodeDouble * requestCodeDouble - 2 * requestCodeDouble;
long p2 = (requestCodeDouble - 2) * (requestCodeDouble - 1);
long p3 = (requestCodeDouble + 2 * requestCodeDouble);
txtSerialNumber.Text = string.Format("{0}-{1}-{2}", p1, p2, p3);
在该方法的最后一部分,使用string.format来创建序列号字符串。
应用程序的最后一个重要部分是确认序列号。这个功能检查两个条件。首先检查请求码和硬盘码是否相等。其次检查所有序列号部分是否正确。
在处理程序的第一部分,检索了当前计算机的请求码。
string thisComputerHddSerialNumber = GetHDDSerialNumber();
byte[] thisComputerRequestCode = new byte[thisComputerHddSerialNumber.Length];
int counter = 0;
foreach (char c in thisComputerHddSerialNumber.ToArray()) {
thisComputerRequestCode[counter] = Convert.ToByte(c.ToString());
counter++;
}
string thisComputerRequestCodeString = Convert.ToBase64String(thisComputerRequestCode);
long p1 = userRequestCodeDouble * userRequestCodeDouble - 2 * userRequestCodeDouble;
long p2 = (userRequestCodeDouble - 2) * (userRequestCodeDouble - 1);
long p3 = (userRequestCodeDouble + 2 * userRequestCodeDouble);
在处理程序方法的第二部分,用户的请求码被转换为double变量。请注意,在本示例中,在同一台计算机上运行应用程序的三个不同部分。但在序列号应用程序的实际使用中,应用程序的三个不同部分在两台或三台不同的计算机上运行。因此,这就是为什么需要再次检索当前计算机的请求码。实际上,比较了用户序列号和请求码与基于系统硬件的正确序列号和请求码。
byte[] userNumberByte = Convert.FromBase64String(txtRequestCode.Text);
string userRequestCode = "";
foreach (byte b in userNumberByte) {
userRequestCode += b.ToString();
}
long userRequestCodeDouble = Convert.ToInt64(userRequestCode);
string[] parts = txtSerialNumber.Text.Split(new string[] { "-" }, StringSplitOptions.RemoveEmptyEntries);
long p1c = Convert.ToInt64(parts[0]);
long p2c = Convert.ToInt64(parts[1]);
long p3c = Convert.ToInt64(parts[2]);
现在拥有所有需要的:
在这里,只需要比较这些变量。
if (p1c == p1 && p2c == p2 && p3c == p3 && userRequestCode == txtRequestCode.Text) {
lblResult.Text = "Correct";
} else {
lblResult.Text = "Wrong";
}