什么是好的唯一PC标识符?

时间:2010-08-09 18:41:05

标签: c# .net guid

我一直在查看this tutorial中的代码,我发现它使用My.Computer.Name来保存不应在计算机之间漫游的设置。但是,完全有可能用户拥有两台名称相同的PC。例如,如果他们想在每台PC上使用相同的用户名,他们最终可能会得到两台名为Username-PC的PC。

识别不同PC有哪些好方法? PC是否有与之关联的GUID,或者我应该考虑从某些硬件中提取序列号?我不关心通过重新安装Windows是否仍然存在识别。

(我链接的教程是在VB.Net中,但我在C#中实现它)

13 个答案:

答案 0 :(得分:43)

一些好的标识符:

  • MAC地址:它很容易上手,而且通常是独一无二的。但是,它可以很容易地被欺骗/改变,因此它取决于它需要多么独特。
  • CPU序列号:它不适用于许多旧系统,但它就在那里。查看this MSDN page。它不会改变,但它与计算机绑定。
  • 硬盘序列号:它可能不会改变,但如果HD出现故障可能会令人讨厌。查看this MSDN page

答案 1 :(得分:18)

如果你在Windows上HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\ CurrentVersion\ProductId每台机器/每个Windows安装都是唯一的。在某些其他答案中,如MAC地址,Proc SN和HD SN将在Windows重新安装/双启动情况之间保持不变。

答案 2 :(得分:11)

这个问题的真正答案:没有这样的事情。

有几个“足够接近”的解决方案,但每个解决方案都有自己的限制。

所有硬件ID - 硬件更改。并且,在许多情况下,您可以更改这些标识符(例如,MAC欺骗)。

正如我已经评论的那样,SID也不是那么好,因为如果从图像安装计算机,SID不会改变。 SID是由Windows安装生成的,如果未安装Windows,但是从图像复制,则SID不会更改(尽管由于myth about "security risk"而重新生成它 - 您不能指望这一点)。

计算机名称 - 嗯,如上所述,他们认为它是独一无二的,但它没有以任何方式强制执行。

您可以实现的另一个解决方案是生成您自己的唯一标识符并将其存储在本地(假设您可以执行此类操作)。同样,如果您的计算机是使用您的应用程序成像的,那么此解决方案将无效。

最适合您的解决方案取决于您要完成的任务。 我有一个相当大的网络问题,在我的情况下,最好的解决方案是计算机的名称。 如果您完全确定您的进程不会被成像,我会使用Guid生成一个唯一的标识符,因为它可能是最安全的。

答案 3 :(得分:9)

这是一种唯一识别计算机的方法。 使用System.Management获取Win32_BIOS,您可以从计算机的BIOS中获取唯一值。

请参阅:Win32_BIOS类,http://msdn.microsoft.com/en-us/library/aa394077.aspx

using System.Management;

string UniqueMachineId()
{
    StringBuilder builder = new StringBuilder();

    String query = "SELECT * FROM Win32_BIOS";
    ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);
    //  This should only find one
    foreach (ManagementObject item in searcher.Get())
    {
        Object obj = item["Manufacturer"];
        builder.Append(Convert.ToString(obj));
        builder.Append(':');
        obj = item["SerialNumber"];
        builder.Append(Convert.ToString(obj));
    }

return builder.ToString();
}

使用类似的逻辑,您也可以单步执行“Win32_DiskDrive”; http://msdn.microsoft.com/en-us/library/aa394132.aspx; 并为每个物理驱动器获取“SerialNumber”。在这种情况下,

    foreach (ManagementObject item in searcher.Get())

应该找到多个项目

答案 4 :(得分:3)

取三个半独特和半常数的标识符。使用3个中的2个足以进行肯定识别的规则。更新偶尔出错的3个中的1个的注册数据。

答案 5 :(得分:2)

使用网卡的MAC地址。它应该是独一无二的。但它可以改变。这取决于您对用户的期望程度以及您的应用程序的重要程度。

一些示例代码:

public string GetMACAddress() {
    ManagementClass mc = new ManagementClass("Win32_NetworkAdapterConfiguration");
    ManagementObjectCollection moc = mc.GetInstances();

    string MACAddress = String.Empty;

    foreach (ManagementObject mo in moc) {
        if (MACAddress == String.Empty) { // only return MAC Address from first card
            if ((bool)mo["IPEnabled"] == true) MACAddress = mo["MacAddress"].ToString();
        }
        mo.Dispose();
    }

    return MACAddress;
}

答案 6 :(得分:1)

您可以使用的一件事是任何网络接口的MAC。您还可以组合多种信息来源。像HDD序列号,mac,处理器类型一样从中计算哈希值。

答案 7 :(得分:0)

我认为在同一个域中有两个同名的PC是不可能的。您是否尝试过捕获域名?

答案 8 :(得分:0)

看看这里:Getting Service Tag from Dell Machine using .net?

您可以从注册表中抓取一些独特的数据。

答案 9 :(得分:0)

每台计算机都有一个在正常情况下唯一的SID。

答案 10 :(得分:0)

在受管网络环境中,最好,最可靠的标识符可能是您创建的 标识符,但是存在一些缺点。

一些(许多?)制造商提供了一个实用程序,可让您设置存储在固件中的资产标签。这可能是可引导的实用程序,或者可能在Windows中运行,甚至可能内置在固件设置中。此“标签”是一个任意文本字符串,您可以将其设置为任意文本,然后使用WMIWin32_SystemEnclosure class ...

读回。
string[] selectedProperties = new string[] { "SMBIOSAssetTag" };
ObjectQuery enclosureQuery = new SelectQuery("Win32_SystemEnclosure", null, selectedProperties);

using (ManagementObjectSearcher enclosureSearcher = new ManagementObjectSearcher(enclosureQuery))
using (ManagementObjectCollection enclosureCollection = enclosureSearcher.Get())
{
    foreach (ManagementObject enclosure in enclosureCollection)
    {
        string assetTag = (string) enclosure.GetPropertyValue("SMBIOSAssetTag");
    }
}

优点:

  • 您可以使用所需的任何方案(例如,合并日期,部门,递增整数,GUID等)。
  • 您可以对所有机器使用一个方案,而不管它们的制造商如何,而不必处理制造商特定的方案。
  • 通过自己分配和跟踪标识符,您可以保证它们是唯一的。不依赖制造商设置的标识符意味着没有制造商内部或制造商之间重复的风险。
  • 标识符存储在固件中,而不是存储在硬盘中,因此它可以在重新格式化,升级等过程中幸存下来,但也不会被备份/映像/克隆所复制。

缺点:

  • 您需要实际设置资产标签;除非您这样做,否则它们都是空白。
  • 设置机器的资产标签可能需要物理访问并重新启动。
  • 资产标签不是一次写入的,因此可以更改或擦除。
    • 受密码保护的固件应该在更改标签之前需要该密码,但这不能保证。
  • 通过自己分配和跟踪标识符,不仅会产生...分配和跟踪标识符的开销,而且如果不小心,可能会引入重复项。
  • 为此目的使用资产标签需要所有机器支持设置资产标签 并将其正确报告给WMI。

答案 11 :(得分:0)

我们结合使用了ProcessorID中的Win32_processorUUID中的Win32_ComputerSystemProduct

ManagementObjectCollection mbsList = null;
ManagementObjectSearcher mos = new ManagementObjectSearcher("Select ProcessorID From Win32_processor");
mbsList = mos.Get();
string processorId = string.Empty;
foreach (ManagementBaseObject mo in mbsList)
{
    processorId = mo["ProcessorID"] as string;
}

mos = new ManagementObjectSearcher("SELECT UUID FROM Win32_ComputerSystemProduct");
mbsList = mos.Get();
string systemId = string.Empty;
foreach (ManagementBaseObject mo in mbsList)
{
    systemId = mo["UUID"] as string;
}

var compIdStr = $"{processorId}{systemId}";

以前,我们使用了以下组合:处理器ID("Select ProcessorID From Win32_processor")和主板序列号("SELECT SerialNumber FROM Win32_BaseBoard"),但随后发现主板序列号可能没有填写,或者可以用统一的值填充

  • 由O.E.M.填补
  • 没有
  • 默认字符串

因此,值得考虑这种情况。

还请记住,ProcessorID号在不同的计算机上可能是相同的。

答案 12 :(得分:-1)

有一个带有完整注释here

的示例代码