生成唯一的计算机ID

时间:2008-09-19 05:30:04

标签: windows winapi wmi uniqueidentifier

我需要编写一个函数来生成一个对于运行Windows操作系统的给定计算机唯一的id。

目前,我正在使用WMI查询各种硬件参数并将它们连接在一起并散列它们以获得唯一ID。我的问题是,我应该使用的建议参数是什么? 目前,我正在使用bios \ cpu \ disk数据的组合来生成唯一ID。如果每个指标有多个结果,我会使用第一个结果。

但是,我遇到了一个问题,即双引导到2个不同Windows操作系统的机器会在每个操作系统上生成不同的站点代码,理想情况下不会发生这种情况。

供参考,这些是我目前使用的指标:

Win32_Processor:UniqueID,ProcessorID,Name,Manufacturer,MaxClockSpeed
Win32_BIOS:Manufacturer
Win32_BIOS:SMBIOSBIOSVersion,IdentificationCode,SerialNumber,ReleaseDate,Version
Win32_DiskDrive:Model, Manufacturer, Signature, TotalHeads
Win32_BaseBoard:Model, Manufacturer, Name, SerialNumber
Win32_VideoController:DriverVersion, Name

15 个答案:

答案 0 :(得分:71)

我遇到了同样的问题,经过一些研究后我决定最好在注册表项MachineGuid中阅读HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography,正如@Agnus建议的那样。它是在操作系统安装期间生成的,除非您再安装新的操作系统,否则不会更改。根据操作系统版本,它可能包含嵌入的网络适配器MAC地址(加上一些其他数字,包括随机数)或伪随机数,后者适用于较新的操作系统版本(在XP SP2之后,我相信,但不确定)。如果它是伪随机的理论上它可以伪造 - 如果两台机器具有相同的初始状态,包括实时时钟。在实践中,这种情况很少见,但请注意,如果您希望它成为可能受到核心黑客攻击的安全基础。

当然,任何人都可以轻松更改注册表项以伪造机器GUID,但我发现这会破坏Windows的许多组件的正常操作,在大多数情况下,没有普通用户会这样做(再次,留意核心黑客。)

答案 1 :(得分:30)

使用我们的licensing tool,我们会考虑以下组件

  • MAC地址
  • CPU(不是序列号,而是实际的CPU配置文件,如步进和模型)
  • 系统驱动器序列号(非卷标)
  • 内存
  • CD-ROM型号&供应商
  • 视频卡型号&供应商
  • IDE控制器
  • SCSI控制器

但是,我们不是仅仅对组件进行散列并创建通过/失败系统,而是创建一个comparable fingerprint,可用于确定两个机器配置文件的不同之处。如果差额评级高于指定的公差,则要求用户再次激活。

我们发现,在过去8年中,数十万个最终用户安装使用这种组合可以很好地提供可靠的唯一机器ID - 即使对于虚拟机和克隆的操作系统安装也是如此。

答案 2 :(得分:23)

自己解析SMBIOS并将其散列为任意长度。有关所有可用的SMBIOS结构,请参阅PDF specification

要从Windows查询SMBIOS信息,您可以使用EnumSystemFirmwareEntriesEnumSystemFirmwareTablesGetSystemFirmwareTable

IIRC,CPUID指令中的“唯一ID”已从P3及更新版本弃用。

答案 3 :(得分:2)

如果只使用处理器的UniqueID呢?

答案 4 :(得分:2)

我不想成为那个说“你只是做错了”的人(我总是讨厌那个人;)但是......

是否必须为独特机器重复生成?您可以只分配标识符或执行公钥/私钥吗?也许如果您可以生成并存储该值,您可以从同一磁盘上的两个操作系统安装中访问它吗?

您可能已经探索过这些选项并且它们不适合您,但如果没有,则需要考虑。

如果这不是用户信任的问题,您可以使用MAC地址。

答案 5 :(得分:1)

您应该考虑使用网卡上的MAC地址(如果存在)。这些通常是独一无二的,但可以制作。我使用的软件根据您的网络适配器MAC地址生成许可文件,因此它被认为是区分计算机的一种相当可靠的方法。

答案 6 :(得分:1)

在我的程序中,我首先检查终端服务器并使用WTSClientHardwareId。否则本地PC的MAC地址就足够了。

如果您真的想要使用您提供的属性列表,请忽略NameDriverVersionClockspeed等内容,因为它可能依赖于操作系统。尝试在两个操作系统上输出相同的信息,并省略不同的信息。

答案 7 :(得分:1)

对于我的某个应用程序,如果它是非域计算机,则使用计算机名称,或者对域计算机使用域计算机帐户SID。 Mark Russinovich在这篇博客文章Machine SID中谈到了它:

  

如果分布式应用程序使用计算机SID来唯一标识计算机,则SID重复将成为问题的最后一种情况。没有Microsoft软件这样做,并且以这种方式使用机器SID不仅仅适用于所有DC具有相同的机器SID的事实。依赖于唯一计算机标识的软件使用计算机名称或计算机域SID(域中计算机帐户的SID)。

您可以通过LDAP或System.DirectoryServices访问域计算机帐户SID。

答案 8 :(得分:1)

有一个库可用于获取特定于硬件的信息:Hardware serial number extractor (CPU, RAM, HDD, BIOS)

答案 9 :(得分:0)

为什么不使用网卡的MAC地址?

答案 10 :(得分:0)

可能有点作弊,但机器以太网适配器的MAC地址在这些天没有改变主板的情况下很少改变。

答案 11 :(得分:0)

您可以提取某种制造商序列号或服务标签吗?

我们的商店是戴尔商店,因此我们使用每台机器独有的服务标签来识别它们。我知道可以从BIOS查询,至少在Linux中,但我不知道如何在Windows中进行操作。

答案 12 :(得分:0)

我还有一个额外的约束,我使用的是.net express,因此无法使用标准的硬件查询机制。因此,我决定使用Power Shell进行查询。完整的代码如下:

Private Function GetUUID() As String
    Dim GetDiskUUID As String = "get-wmiobject Win32_ComputerSystemProduct  | Select-Object -ExpandProperty UUID"
    Dim X As String = ""
    Dim oProcess As New Process()
    Dim oStartInfo As New ProcessStartInfo("powershell.exe", GetDiskUUID)
    oStartInfo.UseShellExecute = False
    oStartInfo.RedirectStandardInput = True
    oStartInfo.RedirectStandardOutput = True
    oStartInfo.CreateNoWindow = True
    oProcess.StartInfo = oStartInfo
    oProcess.Start()
    oProcess.WaitForExit()
    X = oProcess.StandardOutput.ReadToEnd
    Return X.Trim()
End Function

答案 13 :(得分:-1)

查找一个选项的CPUID。多CPU系统可能存在一些问题。

答案 14 :(得分:-1)

试试这个,它会提供一个唯一的硬盘ID:Port of DiskId32 for Delphi 7-2010