在软件安装的时候,常常要验证软件的有效性,这时候发行产品的时候会附带一个USB Key,主程序运行的时候检查这个Key的合法性,如果通过验证,那么启动主程序。
下面的代码提供了实现该方法的途径:
  1. /// <summary>
  2. /// USB 操作相关
  3. /// </summary>
  4. public class UsbUtility
  5. {
  6. const string Key_File_Name = "Usb.key";
  7. /// <summary>
  8. /// 获取优盘唯一序列号,可能需要以管理员身份运行程序
  9. /// </summary>
  10. /// <returns></returns>
  11. public static string GetUSBId()
  12. {
  13. ManagementObjectSearcher wmiSearcher = new ManagementObjectSearcher("Select * From Win32_USBHub");
  14. string id = "";
  15. foreach (ManagementObject wmi_USB in wmiSearcher.Get())
  16. {
  17. string strPath = wmi_USB.Path.RelativePath;
  18. string[] strArr = strPath.Split('/"');
  19. string strTemp = strArr[1];
  20. //VID_ 是真正的优盘标示
  21. if (strTemp.StartsWith("USBVID_"))
  22. id += strTemp + ";";
  23. }
  24. return id.TrimEnd(';');
  25. }
  26. /// <summary>
  27. /// 获取当前UsbKey,根据当前附加的序列号,生成 "序列号,UsbId"格式的字符串,并返回加密后的结果
  28. /// 如果没有找到设备,那么返回空字符串
  29. /// 如果返回值为空,请检查 message 的值。
  30. /// </summary>
  31. /// <param name="sourceNumber">要附加的序列号</param>
  32. /// <param name="message">生成的操作信息</param>
  33. /// <returns>当前加密后的UsbKey字符串</returns>
  34. public static string  GetCurrentUsbKey(string sourceNumber,out string message)
  35. {
  36. string strUsbId = GetUSBId();
  37. if (strUsbId != "")
  38. {
  39. if (strUsbId.Split(';').Length == 1)
  40. {
  41. CheckCode cc = new CheckCode();
  42. message = "OK";
  43. string strTemp = sourceNumber+","+strUsbId ;
  44. return cc.Encode(strTemp);
  45. }
  46. else
  47. {
  48. message = "当前有多个U盘,请拨除其它U盘。";
  49. return "";
  50. }
  51. }
  52. message = "未找到U盘或者U盘没有物理序列号。";
  53. return "";
  54. }
  55. /// <summary>
  56. /// 将一个新的UsbKey写到当前U盘上
  57. /// </summary>
  58. /// <param name="sourceNumber">U盘所在盘符</param>
  59. /// <param name="sourceNumber">要附加的序列号</param>
  60. /// <param name="message">生成的操作信息</param>
  61. /// <returns></returns>
  62. public static bool WriteUsbKeyFile(string driveName, string sourceNumber,out string message)
  63. {
  64. string strCurrentUsbKey = GetCurrentUsbKey(sourceNumber, out message);
  65. if (strCurrentUsbKey != "")
  66. {
  67. if (driveName.EndsWith("//"))
  68. driveName += "//";
  69. string strCurrKeyFileName = driveName + Key_File_Name;
  70. try
  71. {
  72. using (StreamWriter writer = File.CreateText(strCurrKeyFileName))
  73. {
  74. writer.Write(strCurrentUsbKey);
  75. writer.Flush();
  76. }
  77. message = "OK";
  78. return true;
  79. }
  80. catch (Exception ex)
  81. {
  82. message = ex.Message;
  83. }
  84. }
  85. return false;
  86. }
  87. /// <summary>
  88. /// 读取UsbKey文件的内容,返回内容格式为 "序列号,UsbId"格式的字符串
  89. /// 如果未能正确读取文件,返回空字符。
  90. /// </summary>
  91. /// <param name="driveName">U盘所在盘符</param>
  92. /// <param name="message">操作的消息</param>
  93. /// <returns>UsbKey文件的内容</returns>
  94. public static string  ReadUsbKeyFile(string driveName, out string message)
  95. {
  96. if (driveName.EndsWith("//"))
  97. driveName += "//";
  98. string strCurrKeyFileName = driveName + Key_File_Name;
  99. message = "";
  100. try
  101. {
  102. string strResult = "";
  103. using (StreamReader reader = File.OpenText(strCurrKeyFileName))
  104. {
  105. strResult = reader.ReadToEnd();
  106. }
  107. if (strResult != "")
  108. {
  109. message = "OK";
  110. CheckCode cc = new CheckCode();
  111. return cc.Decode(strResult);
  112. }
  113. else
  114. {
  115. message = "未能正确读取文件,文件内容可能为空!";
  116. }
  117. }
  118. catch (Exception ex)
  119. {
  120. message = ex.Message;
  121. }
  122. return "";
  123. }
  124. }
  125. /// <summary>
  126. /// 检查编码情况
  127. /// </summary>
  128. class CheckCode
  129. {
  130. const string KEY_64 = "fasfgew";
  131. const string IV_64 = "JDLJMAMI"; //注意了,是8个字符,64位
  132. /// <summary>
  133. /// 加密
  134. /// </summary>
  135. /// <param name="data"></param>
  136. /// <returns></returns>
  137. public string Encode(string data)
  138. {
  139. byte[] byKey = System.Text.ASCIIEncoding.ASCII.GetBytes(KEY_64);
  140. byte[] byIV = System.Text.ASCIIEncoding.ASCII.GetBytes(IV_64);
  141. DESCryptoServiceProvider cryptoProvider = new DESCryptoServiceProvider();
  142. int i = cryptoProvider.KeySize;
  143. MemoryStream ms = new MemoryStream();
  144. CryptoStream cst = new CryptoStream(ms, cryptoProvider.CreateEncryptor(byKey, byIV), CryptoStreamMode.Write);
  145. StreamWriter sw = new StreamWriter(cst);
  146. sw.Write(data);
  147. sw.Flush();
  148. cst.FlushFinalBlock();
  149. sw.Flush();
  150. return Convert.ToBase64String(ms.GetBuffer(), 0, (int)ms.Length);
  151. }
  152. /// <summary>
  153. /// 解密
  154. /// </summary>
  155. /// <param name="data"></param>
  156. /// <returns></returns>
  157. public string Decode(string data)
  158. {
  159. byte[] byKey = System.Text.ASCIIEncoding.ASCII.GetBytes(KEY_64);
  160. byte[] byIV = System.Text.ASCIIEncoding.ASCII.GetBytes(IV_64);
  161. byte[] byEnc;
  162. try
  163. {
  164. byEnc = Convert.FromBase64String(data);
  165. }
  166. catch
  167. {
  168. return null;
  169. }
  170. DESCryptoServiceProvider cryptoProvider = new DESCryptoServiceProvider();
  171. MemoryStream ms = new MemoryStream(byEnc);
  172. CryptoStream cst = new CryptoStream(ms, cryptoProvider.CreateDecryptor(byKey, byIV), CryptoStreamMode.Read);
  173. StreamReader sr = new StreamReader(cst);
  174. return sr.ReadToEnd();
  175. }
  176. }

在主窗体,使用下面的代码调用:

  1. private void btnMakeUsbKey_Click(object sender, EventArgs e)
  2. {
  3. string strMessage = "";
  4. MakeProductNumbers();
  5. if (UsbUtility.WriteUsbKeyFile(CurrentUSBDriveName, ProductNumbers, out strMessage))
  6. {
  7. MessageBox.Show("Usb Key File 生成成功!");
  8. }
  9. else
  10. {
  11. MessageBox.Show(strMessage);
  12. }
  13. }
  14. private void btnShowUsbKey_Click(object sender, EventArgs e)
  15. {
  16. string strMessage = "";
  17. string strText = UsbUtility.ReadUsbKeyFile(CurrentUSBDriveName, out strMessage);
  18. if (strText!="")
  19. {
  20. MessageBox.Show(strText,"查看USBKEY");
  21. }
  22. else
  23. {
  24. MessageBox.Show(strMessage,"Error");
  25. }
  26. }
  27. private string _CurrentUSBDriveName = "";
  28. /// <summary>
  29. /// 当前USB 驱动器号
  30. /// </summary>
  31. public string CurrentUSBDriveName
  32. {
  33. get
  34. {
  35. if (_CurrentUSBDriveName == "")
  36. {
  37. string[] strDrivers = Environment.GetLogicalDrives();
  38. _CurrentUSBDriveName = strDrivers[strDrivers.Length - 1];
  39. }
  40. return _CurrentUSBDriveName;
  41. }
  42. set
  43. {
  44. _CurrentUSBDriveName = value ;
  45. }
  46. }

属性 CurrentUSBDriveName 会返回当前最后一个驱动器号,我们认为它是优盘,但是这不是很保险。为此,我们需要监视系统合适插入了U盘,并取得它的盘符。

在主窗体中(一定要在主窗体中,不能再用户控件中),加入下面的代码:
  1. public const int WM_DEVICECHANGE = 0x219;
  2. public const int DBT_DEVICEARRIVAL = 0x8000;
  3. public const int DBT_CONFIGCHANGECANCELED = 0x0019;
  4. public const int DBT_CONFIGCHANGED = 0x0018;
  5. public const int DBT_CUSTOMEVENT = 0x8006;
  6. public const int DBT_DEVICEQUERYREMOVE = 0x8001;
  7. public const int DBT_DEVICEQUERYREMOVEFAILED = 0x8002;
  8. public const int DBT_DEVICEREMOVECOMPLETE = 0x8004;
  9. public const int DBT_DEVICEREMOVEPENDING = 0x8003;
  10. public const int DBT_DEVICETYPESPECIFIC = 0x8005;
  11. public const int DBT_DEVNODES_CHANGED = 0x0007;
  12. public const int DBT_QUERYCHANGECONFIG = 0x0017;
  13. public const int DBT_USERDEFINED = 0xFFFF;
  14. protected override void WndProc(ref Message m)
  15. {
  16. try
  17. {
  18. if (m.Msg == WM_DEVICECHANGE)
  19. {
  20. switch (m.WParam.ToInt32())
  21. {
  22. case WM_DEVICECHANGE:
  23. break;
  24. case DBT_DEVICEARRIVAL://U盘插入
  25. DriveInfo[] s = DriveInfo.GetDrives();
  26. foreach (DriveInfo drive in s)
  27. {
  28. if (drive.DriveType == DriveType.Removable)
  29. {
  30. mpnUC.CurrentUSBDriveName  = drive.Name.ToString();
  31. //
  32. MessageBox.Show("U盘已插入,盘符为:" + drive.Name.ToString() + "/r/n");
  33. break;
  34. }
  35. }
  36. break;
  37. case DBT_CONFIGCHANGECANCELED:
  38. break;
  39. case DBT_CONFIGCHANGED:
  40. break;
  41. case DBT_CUSTOMEVENT:
  42. break;
  43. case DBT_DEVICEQUERYREMOVE:
  44. break;
  45. case DBT_DEVICEQUERYREMOVEFAILED:
  46. break;
  47. case DBT_DEVICEREMOVECOMPLETE: //U盘卸载
  48. MessageBox.Show("U盘已卸载!");
  49. break;
  50. case DBT_DEVICEREMOVEPENDING:
  51. break;
  52. case DBT_DEVICETYPESPECIFIC:
  53. break;
  54. case DBT_DEVNODES_CHANGED:
  55. break;
  56. case DBT_QUERYCHANGECONFIG:
  57. break;
  58. case DBT_USERDEFINED:
  59. break;
  60. default:
  61. break;
  62. }
  63. }
  64. }
  65. catch (Exception ex)
  66. {
  67. MessageBox.Show(ex.Message);
  68. }
  69. base.WndProc(ref m);
  70. }
mpnUC 是一个用户控件,我们设置了它的  CurrentUSBDriveName  属性。
OK,允许程序,我们就生成了一个USB Key 了。

根据USB 序列号 生成USB Key相关推荐

  1. 使用STM32CubeMX 快速生成 USB HID 工程 - STM32F107VCT6

    背景 最近在研究USB Device通信,如USB HID .USB Device. 使用STM32CubeMX,可以快速生成 USB HID .USB Device的工程. 学习USB,通过实践的方 ...

  2. python生成USB播放器歌单

    用python生成USB播放器歌单 个人比较喜欢听歌,前段时间还买了个可以插U盘和储存卡的播放器,它支持直接按数字跳转歌曲,但自己却不知道歌曲对应的号码. 测试发现歌曲顺序并不是按文件名排序,也不是按 ...

  3. 使用STM32CubeMX生成USB驱动程序 USB无法检测到的问题 生成USB驱动

    以STM32CubeMX生成USB驱动为例,其步骤如下: 一.使用STM32CubeMX生成USB驱动程序 打开STM32CubeMX软件,选择Start My project formMCU,点AC ...

  4. [FAQ10927][USB serial number客制化][系列6]:能否实现adb devices的序列号,usb serialnumber, cts device ID,SN一致?

    [DESCRIPTION] 能否实现adb devices的序列号,usb serial number, cts device ID,SN一致? [KEYWORD] adb devices, Seri ...

  5. USB耳机方案|USB麦克风方案|SSS1629方案设计

    USB耳机方案|USB麦克风方案|SSS1629方案设计 一.SSS1629/3S1629产品描述: SSS1629/3S1629除了传统 USB 耳麦芯片所具有的基本功能外,SSS1629-A5(3 ...

  6. linux usb组合设备,USB组合设备(5)

    最近做一个组合设备,说白了就是在一个usb 设备上面,实现2个或者更多功能,但是说实话中文的资料还是比较少,没找到多少比较靠谱的,就去外文网站翻翻了 还是不少的,下面我将自己的理解理清改一下,希望也可 ...

  7. 关于流水帐表序列号生成时的并发操作问题

    关于流水帐表序列号生成时的并发操作问题 1.某些流水张表的序号不是而是带有一定规则的,   如:四位的年份+2位周数+7位数字的序号       2007130000002.   假定表的定义如下: ...

  8. Android通过cat /sys/kernel/debug/usb/devices获取USB信息

    cat /sys/kernel/debug/usb/devices得到的信息如下 下图是我们产品USB 拓扑图 USB设备通过debugfs导出/sys/kernel/debug/usb/device ...

  9. .NET平台开源项目速览(9)软件序列号生成组件SoftwareProtector介绍与使用

    原文:.NET平台开源项目速览(9)软件序列号生成组件SoftwareProtector介绍与使用 在文章:这些.NET开源项目你知道吗?让.NET开源来得更加猛烈些吧!(第二辑)中,给大家初步介绍了 ...

最新文章

  1. Bitmap Cache
  2. 二维绕任意点旋转_二维图形复合线性变换程序设计:三角形绕任意点旋转2wfhbh...
  3. 龙芯完成.NET移植稳步推进生态建设
  4. 如何禁用计算机的服务,如何彻底禁用电脑中的迅雷服务XLservicePlatform
  5. C++之 字符串拷贝函数(面试题目)
  6. NetSuite二次开发服务改变中小企业发展困境!
  7. python学习笔记-Day5
  8. 序列标注模型结果评估模块seqeval学习使用
  9. rabbitMq多个队列多种任务同时监听
  10. 一文带你详解矩阵键盘工作原理
  11. sql 计算周环比wow_Oracle计算环比的方法
  12. 记一次阿里云面试心得
  13. taobao tt 配置
  14. 洛谷P1873 [COCI 2011/2012 #5] EKO / 砍树(二分法)
  15. python嵌入式系统开发_图解嵌入式系统开发之语言篇:初识Python
  16. 微信小程序常见面试题
  17. 大数据开发课程:大数据开发培训课程
  18. org.json.JSONException: Value [{“id“:10,“userId“:6,“adminId“:5,“content“:“7777“,“state“:-1,“image1“:
  19. 求解关系模式R的候选码
  20. python怎么撤销_关于Python:Python-如何删除/取消导入之前已导入的库

热门文章

  1. JAVA并发-AtomicLong
  2. STM32外部中断解析
  3. 第二章 VUE数据绑定和渲染(1)
  4. C++四舍五入以及小数点后两位进行舍入
  5. 1、如何快速在windows上创建你的第一个odoo项目
  6. [NOTE]Android N SmartLock缺少很多功能
  7. 详谈高性价比的推广方法有哪些
  8. java实现MinIO文件上传,并将视频文件截图,将视频封面及视频通过MinIo上传到服务器中
  9. JAVA中静态方法的调用
  10. [Hyper-v]删除系统保留分区,修复克隆win7/win8虚拟磁盘后无法引导问题