前幾天在博客園里面看到有個人分享了一篇注冊碼的代碼,密密麻麻的還不可以運行,於是自己根據他的思路,把這個工作完成了。這里也是抱着分享的態度和大家交流一下。希望各位高手手下留情。
首先我們需要引入一下using System.Management;這個類庫。
然后我們定義一下字段並設置其屬性為只讀。
具體代碼如下:
private string _CPU; // CPU private string _DiskVolumeSerialNumber; // DiskVolumeSerialNumber private string _MachineNum; // MachineNum private string _RegNum; // RegNum private int[] intCode = new int[127]; // 存儲密鑰 private int[] intNumber = new int[25]; // 存機器碼的Ascii值 private char[] Charcode = new char[25]; // 存儲機器碼字 private int _Times; // 設置軟件使用的次數 private string _regKey; // 設置注冊表的Key值 private bool _isRegNum; // 判斷是否需要注冊
/// <summary> /// CPU 字符串 /// </summary> public string CPU { get { return _CPU; } } public string DiskVolumeSerialNumber { get { return _DiskVolumeSerialNumber; } } public string MachineNum { get { return _MachineNum; } } public string RegNum { get { return _RegNum; } } public int Times { get { return _Times; } } public string RegKey { set { _regKey = value; } } public bool IsRegNum { get { return _isRegNum; } set { _isRegNum = value; } }
這里我們可以通過兩個構造函數去聲明來構造我們的對象。其中一個是帶參數的,另一個是不帶參數的。其中不帶參數的需要在創建完對象之后再去設置其屬性。
#region 構造函數 public RegClass() { this._CPU = getCPU(); this._DiskVolumeSerialNumber = GetDiskVolumeSerialNumber(); this._MachineNum = getMNum(); this._RegNum = getRNum(); } public RegClass(int times,string regKey) { this._Times = times; this._regKey = regKey; this._CPU = getCPU(); this._DiskVolumeSerialNumber = GetDiskVolumeSerialNumber(); this._MachineNum = getMNum(); this._RegNum = getRNum(); } #endregion
最后我們需要一步一步的寫其中每一個方法。具體還是看代碼吧:
#region 函數 /// <summary> /// 獲取CPU /// </summary> /// <returns>CPU字符串</returns> public string getCPU() { string strCPU = null; ManagementClass myCPU = new ManagementClass("win32_Processor"); ManagementObjectCollection myCPUConnection = myCPU.GetInstances(); foreach (ManagementObject myObject in myCPUConnection) { strCPU = myObject.Properties["Processorid"].Value.ToString(); break; } return strCPU; } /// <summary> /// 獲取卷軸字符串 /// </summary> /// <returns>卷軸字符串</returns> public string GetDiskVolumeSerialNumber() { ManagementClass mc = new ManagementClass("Win32_NetworkAdapterConfiguration"); ManagementObject disk = new ManagementObject("win32_logicaldisk.deviceid=\"d:\""); disk.Get(); return disk.GetPropertyValue("VolumeSerialNumber").ToString(); } /// <summary> /// 得到機器碼 /// </summary> /// <returns>機器碼</returns> public string getMNum() { string strNum = getCPU() + GetDiskVolumeSerialNumber(); //獲得24位Cpu和硬盤序列號 string strMNum = strNum.Substring(0, 24); //從生成的字符串中取出前24個字符做為機器碼 return strMNum; } /// <summary> /// 給數組賦值小於10的數 /// </summary> public void setIntCode() { for (int i = 1; i < intCode.Length; i++) { intCode[i] = i % 9; } } /// <summary> /// 獲得注冊碼 /// </summary> /// <returns>注冊碼字符串</returns> public string getRNum() { setIntCode();//初始化127位數組 for (int i = 1; i < Charcode.Length; i++)//把機器碼存入數組中 { Charcode[i] = Convert.ToChar(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]); } #region 此處代碼 待優化 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(); } } } #endregion return strAsciiName; } /// <summary> /// 是否需要注冊 /// </summary> /// <returns></returns> public bool IsReg() { _Times = LeftTimes(); if (_Times == 0 || _Times == -1) { return false; } return true; } /// <summary> /// 升序的次數 /// </summary> /// <returns>剩余的次數</returns> private int LeftTimes() { RegistryKey rootKey, regKey; rootKey = Registry.CurrentUser.OpenSubKey("Software",true); if ((regKey = rootKey.OpenSubKey(_regKey, true)) == null) { rootKey.CreateSubKey(_regKey); regKey = rootKey.OpenSubKey(_regKey,true); _Times = _Times - 1; regKey.SetValue("LeftTime",(object)(_Times)); return _Times; } object leftTime = regKey.GetValue("LeftTime"); _Times = Int32.Parse(leftTime.ToString()) - 1; if (_Times <= 0) { return -1; } else { regKey.SetValue("LeftTime", (object)(_Times)); return _Times; } } #endregion
這個是我寫的簡單類庫,我們在自己程序的時候 只需要簡單的調用這個類庫,然后去生命這個類的對象就可以了。具體使用如下:
RegClass reg = new JCodesRegLib.RegClass(5, "TestKey"); //其中前面的參數是代表你的應用程序可以被使用的次數,后面那個是注冊碼的名字
private void Form1_Load(object sender, EventArgs e) { textBox1.Text = reg.CPU; textBox2.Text = reg.DiskVolumeSerialNumber; textBox3.Text = reg.MachineNum; textBox4.Text = reg.RegNum; }
當我們程序一開始加載的時候,就去使用得到相應的注冊碼和別的信息。
不足之處
首先我覺得自己設計的時候還是比較簡單的。沒有從大眾的軟件注冊碼設計出發。其中我們的注冊碼設計的原理是根據你的硬件和磁盤信息得到的32位注冊碼。其中還有把一些信息保存的到了注冊表中,但是安全性比較低。我自己也測試過了,如果你的電腦上裝一個Regmon這個軟件,就可以去動態的檢查你的注冊表修改信息。很容易破解。所以在開發的時候,這個只是給初學者了解一下 注冊碼大概的實現過程和c#如何去操作注冊碼這些知識。