代码之家  ›  专栏  ›  技术社区  ›  dlras2

什么是好的个人电脑唯一标识符?

  •  40
  • dlras2  · 技术社区  · 14 年前

    我一直在看 this tutorial My.Computer.Name 保存不应在计算机之间漫游的设置。但是,用户完全有可能拥有两台名称相同的电脑。例如,如果他们想在每台电脑上拥有相同的用户名,他们很可能最终拥有两台名为username-PC的电脑。

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

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

    10 回复  |  直到 14 年前
        1
  •  52
  •   mattbasta    14 年前

    一些好的标识符:

        2
  •  20
  •   Scott Chamberlain    14 年前

    如果你在windows上 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\ CurrentVersion\ProductId 每台计算机/每台windows安装都是唯一的。其中,与其他一些答案一样,MAC地址、Proc SN和HD SN在windows重新安装/双引导情况下保持不变。

        3
  •  11
  •   Dig    12 年前

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

    有几种“足够接近”的解决方案,但每一种都有自己的局限性。

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

    我已经说过,SID也不是很好,因为如果计算机是从映像安装的,SID不会改变。SID是由windows安装生成的,如果没有安装windows,而是从映像中复制的,则SID不会更改(尽管由于 myth about "security risk"

    计算机名——如前所述,它们应该是唯一的,但并没有以任何方式强制执行。

    您可以实现的另一个解决方案是生成您自己的唯一标识符并将其存储在本地(假设您可以这样做)。同样,如果您的计算机与应用程序一起成像,此解决方案将不起作用。

    对你来说,最好的解决方案实际上取决于你想要完成什么。 我在一个相当大的网络上也遇到了同样的问题,最好的解决办法就是计算机名。 如果您绝对确定您的进程不会被映像,我将使用Guid生成一个唯一标识符,因为它可能是最安全的。

        4
  •  9
  •   andrewmcc    11 年前

    使用System.Management 要获取Win32\u BIOS,可以从计算机的BIOS获取唯一值。

    请参阅:Win32\u 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();
    }
    

    http://msdn.microsoft.com/en-us/library/aa394132.aspx 并获取每个实体驱动器的“序列号”。在这种情况下

        foreach (ManagementObject item in searcher.Get())
    

        5
  •  6
  •   Tomminn    7 年前

    取三个半唯一和半常量的标识符。使用三分之二就足以证明身份的规则。更新偶尔出错的三分之一的注册数据。

        6
  •  2
  •   MicSim    14 年前

    使用网卡的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;
    }
    
        7
  •  1
  •   schoetbi    14 年前

    你可以使用任何网络接口的MAC。您还可以组合多个信息源。像HDD序列号,mac,处理器类型来计算散列。

        8
  •  0
  •   user279521    14 年前

    我认为不可能在同一个域上有两台同名的PC。你试过捕获域名吗?

        10
  •  0
  •   Steven Sudit    14 年前

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

        11
  •  0
  •   Lance U. Matthews    4 年前

    你创造了 但也有一些缺点。

    一些(许多?)制造商提供了一个实用程序,允许您设置 资产标签 存储在固件中的。这可能是一个可引导的实用程序,也可能在Windows中运行,甚至可能内置在固件设置中。这个“标签”是一个任意的文本字符串,你可以设置为任何你想要的,然后读回来使用 WMI Win32_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正确报告。
        12
  •  0
  •   Andrej    4 年前

    我们使用 ProcessorID Win32_processor UUID 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}";
    

    "Select ProcessorID From Win32_processor" )以及主板序列号( "SELECT SerialNumber FROM Win32_BaseBoard" ),但后来我们发现主板的序列号可能没有填写,也可能是用统一的值填写的:

    • 没有

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

    还要记住 不同计算机上的数字可能相同。

        13
  •  -1
  •   Sharif Lotfi    4 年前

    http://www.vcskicks.com/hardware_id.php

    将此dll添加到引用

     System.Management.dll
    

    对于CPU ID:

    string cpuInfo = string.Empty;
    ManagementClass mc = new ManagementClass("win32_processor");
    ManagementObjectCollection moc = mc.GetInstances();
    
    foreach (ManagementObject mo in moc)
    {
         if (cpuInfo == "")
         {
              //Get only the first CPU's ID
              cpuInfo = mo.Properties["processorID"].Value.ToString();
              break;
         }
    }
    return cpuInfo;
    

    对于硬盘ID(卷序列号):

    ManagementObject dsk = new ManagementObject(@"win32_logicaldisk.deviceid=""" + drive + @":""");
    dsk.Get();
    string volumeSerial = dsk["VolumeSerialNumber"].ToString();