是否有任何方法可以唯一地识别任何计算机

时间:2012-02-28 12:52:10

标签: c# windows uniqueidentifier

我知道stackoverflow中有很多类似的问题,如下所示:

......还有几十个,我已经研究了所有这些。

问题在于,一些已接受的答案已将MAC地址建议为唯一标识符,这完全不正确。其他一些答案建议使用各种组件的组合,这似乎更合乎逻辑。但是,在使用组合的情况下,应该考虑哪些组件自然不可能经常更换。几天前,我们为软件许可问题开发了一个密钥生成器,我们使用CPUID和MAC的组合来唯一地识别一台Windows PC,直到实际测试我们认为我们的方法已经足够好了。具有讽刺意味的是,当我们进行测试时,我们发现三台计算机使用我们的密钥生成器返回相同的ID!

那么,是否有任何方法可以唯一识别任何计算机?现在我们只需要让我们的密钥生成器在windows pc上运行。使用c#的某种方式(如果可能的话)将是很好的,因为我们的系统是在.net上开发的。

更新

很抱歉造成一些混乱和明显的误报。我们在检索HW信息的方法中发现了一些不正确之处。主要是我想删除这个问题,因为现在我自己的困惑已经消失,我确实认为两个或更多组件的组合足以识别计算机。但是,我决定保留它,因为我认为我应该澄清导致问题的原因,因为同样的事情可能会伤害其他人。

这就是我们正在做的事情(不包括其他代码):

我们使用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;
    } 

然后在需要的地方我们使用该函数来检索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命令在命令提示符中搜索MAC地址时,它显示每个pc的一个或两个MAC地址都是不同的。但是getManagementInfo("Win32_NetworkAdapterConfiguration", "MacAddress")返回了四到五个MAC地址,其中一些对于所有计算机都是相同的。由于我们刚刚获取了我们的函数返回的第一个MAC地址,而不是检查其他任何内容,因此strMAC中的相同MAC地址不可避免。

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地址。我认为我们的目的将以这种方式提供,如果在某些情况下没有,那么我们应该在这几种情况下放手。

5 个答案:

答案 0 :(得分:11)

如何添加主板序列号,例如:

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();
}

答案 1 :(得分:5)

获取全局唯一ID的事实是,只有MAC地址是在您全部设置系统时不会更改的ID。如果要为特定产品生成密钥,最好的方法是为产品分配唯一ID并将产品ID与MAC地址组合。希望能帮助到你。

答案 2 :(得分:2)

我完全同意上述评论。

对于软件许可,您可以使用:

计算机MAC地址(如果有多个NIC卡则全部使用)+您的软件产品代码

大多数着名的电信供应商都在使用这种技术。

答案 3 :(得分:1)

  

但是,我对完全相同的处理器ID完全正确   问题。当我们放入wmic cpu时,所有三个都返回相同的处理器ID   在命令提示符下输入ProcessorId命令。

如果所有系统都在同一个虚拟机管理程序上作为虚拟机运行,则处理器ID将相同。

MAC ID似乎很好。唯一的问题是,如果MAC发生变化,必须为用户提供重置应用程序的选项。

答案 4 :(得分:0)

看来定制厨房是解决问题的方法。

SMBIOS UUID(主板串行)不可靠,但在99%的情况下仍可以正常工作。但是,某些品牌会为多台计算机设置相同的UUID(可能是同一批生产)。要获得它,需要用户(如果不是管理员)具有WMI访问权限,您可以通过启动外部过程询问管理员权限(请检查codeproject.com/Articles/15848/WMI-Namespace-Security)来解决该问题

Windows产品ID可能不错,但我读到它在某些情况下可能是相同的(https://www.nextofwindows.com/the-best-way-to-uniquely-identify-a-windows-machine) 有人可以弄清楚多台计算机上是否可能存在相同的产品ID(而非产品密钥)?

HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Cryptography \ MachineGuid似乎很有趣。它是在安装Windows时生成的,如果进行了更改,则需要重新激活Windows。

Mac地址很有趣,但您只能使用第一个,否则当禁用接口或添加另一个网络接口并首先显示等时,唯一ID将会更改。

硬盘驱动器的序列号很好,但是在安装虚拟驱动器时,它也可能会覆盖原始驱动器中的序列号...而且高清序列号很容易更改。

最好的方法是使用这些机器标识符的组合生成ID,然后通过比较这些标识符来确定机器是否相同(例如,是否至少有一个Mac地址+ SMBIOS UUID或产品ID可以,请接受)