我知道在stackoverflow中有一些类似的问题如下:
…还有几十个,我都研究过了。
问题是,一些被接受的答案已经build议将MAC地址作为唯一的标识符,这是完全不正确的。 其他一些答案build议使用看起来更合乎逻辑的各种组件的组合。 但是,在使用组合的情况下,应该考虑哪个组件自然不太可能经常改变。 几天前,我们开发了一个软件许可问题的密钥生成器,我们使用CPUID和MAC的组合来唯一地识别Windows PC,直到实际testing,我们认为我们的方法是足够好的。 讽刺的是,当我们去testing它时,我们发现有三台电脑用我们的密钥生成器返回相同的ID!
那么,究竟有什么办法来唯一标识任何电脑? 现在我们只需要让我们的密钥生成器在Windows PC上工作。 一些使用c#的方法(如果可能的话)会很好,因为我们的系统是在.net上开发的。
更新:
对不起,造成一些混乱和明显的虚惊。 我们在检索硬件信息的方法中发现了一些不正确的地方。 我主要想到删除这个问题,因为现在我自己的困惑已经消失了,而且我相信两个或更多个组件的组合足以识别一台计算机。 然而,我决定保留它,因为我认为我应该澄清是什么导致问题,因为同样的事情可能会伤害其他人在未来。
这是我们正在做的(不包括其他代码):
我们使用getManagementInfo
函数来检索MAC和处理器ID
private String getManagementInfo(String StrKey_String, String strIndex) { String strHwInfo = null; try { ManagementObjectSearcher searcher = new ManagementObjectSearcher("select * from " + StrKey_String); foreach (ManagementObject share in searcher.Get()) { strHwInfo += share[strIndex]; } } catch (Exception ex) { // show some error message } return strHwInfo; }
然后,在需要的地方,我们使用该function来检索MAC地址
string strMAC = getManagementInfo("Win32_NetworkAdapterConfiguration", "MacAddress");
并检索ProcessorID
string strProcessorId = getManagementInfo("Win32_Processor", "ProcessorId");
此时,如果有多个MAC地址, strMAC
将包含多个MAC地址。 只取一个,我们只取了前17个字符(12个MAC数字和5个冒号)。
strMAC = strMAC.Length > 17 ? strMAC.Remove(17) : strMAC;
这是我们犯了错误的地方。 因为getManagementInfo("Win32_NetworkAdapterConfiguration", "MacAddress")
返回了一些真正在使用的额外MAC地址。 例如,当我们通过getmac
命令在命令提示符中searchMAC地址时,它显示了每个pc的一个或两个MAC地址,这些MAC地址都是不同的。 但getManagementInfo("Win32_NetworkAdapterConfiguration", "MacAddress")
返回了四到五个MAC地址,其中一些对于所有计算机都是相同的。 因为我们只是把我们的函数返回的第一个MAC地址,而不是其他的检查,相同的MAC地址在strMAC
被采取。
Sowkot Osman的以下代码通过仅返回第一个活动/启用的MAC地址来实现:
private static string macId() { return identifier("Win32_NetworkAdapterConfiguration", "MACAddress", "IPEnabled"); } private static string identifier(string wmiClass, string wmiProperty, string wmiMustBeTrue) { string result = ""; System.Management.ManagementClass mc = new System.Management.ManagementClass(wmiClass); System.Management.ManagementObjectCollection moc = mc.GetInstances(); foreach (System.Management.ManagementObject mo in moc) { if (mo[wmiMustBeTrue].ToString() == "True") { //Only get the first one if (result == "") { try { result = mo[wmiProperty].ToString(); break; } catch { } } } } return result; } //Return a hardware identifier private static string identifier(string wmiClass, string wmiProperty) { string result = ""; System.Management.ManagementClass mc = new System.Management.ManagementClass(wmiClass); System.Management.ManagementObjectCollection moc = mc.GetInstances(); foreach (System.Management.ManagementObject mo in moc) { //Only get the first one if (result == "") { try { result = mo[wmiProperty].ToString(); break; } catch { } } } return result; }
不过,我完全正确的处理相同的处理器ID问题。 当我们把wmic cpu get ProcessorId
命令放在他们的命令提示符下时,所有三个处理器都返回相同的处理器ID。
现在我们决定使用主板序列号而不是处理器ID来与MAC地址组合。 我认为我们的目的是这样做的,如果没有,那么我们就应该在这种情况下放手。
获取一个全球唯一的ID的事实是,只有MAC地址是如果你设置你的系统不会改变的ID。 如果您为特定产品生成密钥,则最好的方法是为产品分配唯一的ID,并将产品ID与MAC地址相结合。 希望能帮助到你。
如何添加主板序列号以及如:
using System.management; //Code for retrieving motherboard's serial number ManagementObjectSearcher MOS = new ManagementObjectSearcher("Select * From Win32_BaseBoard"); foreach (ManagementObject getserial in MOS.Get()) { textBox1.Text = getserial["SerialNumber"].ToString(); } //Code for retrieving Processor's Identity MOS = new ManagementObjectSearcher("Select * From Win32_processor"); foreach (ManagementObject getPID in MOS.Get()) { textBox2.Text = getPID["ProcessorID"].ToString(); } //Code for retrieving Network Adapter Configuration MOS = new ManagementObjectSearcher("Select * From Win32_NetworkAdapterConfiguration"); foreach (ManagementObject mac in MOS.Get()) { textBox3.Text = mac["MACAddress"].ToString(); }
我完全同意上面的评论。
对于软件许可,您可以使用:
计算机MAC地址(如果多个NIC卡,请全部使用)+您的软件产品代码
大多数着名的电信厂商正在使用这种技术。
不过,对于相同的处理器ID问题,我是绝对正确的。 当我们把wmic cpu的ProcessorId命令放在他们的命令提示符下时,所有三个处理器都返回相同的处理器ID。
如果所有系统在相同的虚拟机管理程序上作为虚拟机运行,则处理器ID将相同。
MAC ID似乎很好。 唯一的事情是用户必须提供重置应用程序的选项,以防MAC改变。