像 Microsoft 一样获取硬件 ID

问题描述 投票:0回答:4

在 Windows SDK 中有一个名为 computerhardwareids

的 CLI 工具

该工具返回各种 GUID,以便为特定情况选择正确的 HardwareId。

这是在我的电脑中返回此工具的输出:

Using the BIOS to gather information

Computer Information
--------------------

BIOS Vendor: American Megatrends Inc.
BIOS Version string: 1201
System BIOS Major Release: 4
System BIOS Minor Release: 6

System Manufacturer: To be filled by O.E.M.
System Family: To be filled by O.E.M.
System ProductName: To be filled by O.E.M.
SKU Number: SKU

Enclosure Type: 03 "Desktop"


Hardware IDs
------------
{a8670b03-1d98-5e95-ad4e-c64211eac9df}    <- Manufacturer + Family + ProductName + SKUNumber + BIOS Vendor + BIOS Version + BIOS Major Release + BIOS Minor Release
{01c6b2a2-a2b2-58e4-906d-4677639f1a42}    <- Manufacturer + Family + ProductName + BIOS Vendor + BIOS Version + BIOS Major Release + BIOS Minor Release
{dc5af3fe-c2de-539d-aafd-5061a1634723}    <- Manufacturer + ProductName + BIOS Vendor + BIOS Version + BIOS Major Release + BIOS Minor Release
{d78b474d-dee0-5412-bc9d-e9f7d7783df2}    <- Manufacturer + Family + ProductName + SKUNumber
{7ccbb6f1-9641-5f84-b00d-51ff218a4066}    <- Manufacturer + Family + ProductName
{5a127cba-be28-5d3b-84f0-0e450d266d97}    <- Manufacturer + SKUNumber
{6525c6e5-28e9-5f9c-abe4-20fd82504002}    <- Manufacturer + ProductName
{6525c6e5-28e9-5f9c-abe4-20fd82504002}    <- Manufacturer + Family
{482f3f58-6045-593a-9be4-611717ce4770}    <- Manufacturer + Enclosure Type
{11b4a036-3b64-5421-a372-22c07df10a4d}    <- Manufacturer

我想开发一个通用函数,应该模仿该 Microsoft 工具的功能,返回完全相同的 HardwareIds(完全相同)。

我在 MSDN 上找到了信息,所有输出似乎都有详细记录,并且包含有关返回此工具的值的信息,但它没有具体指定 WMI 类的属性是什么,它只是说“Bios”和“系统”:

· 计算机硬件 ID 概述

· 指定计算机的硬件 ID

我很迷茫,我找不到任何值,例如“Family”、“BIOS Vendor”、“Bios Major Release”、“Bios Minor Release”,并且我不确定“SKU Number”指的是什么.

我认为这些是 WMI 类,工具在其中获取所有数据的一部分来制作 guid:

· Win32_BIOS 类

· Win32_BaseBoard 类

· Win32_ComputerSystem 类

· Win32_ComputerSystem产品类

请注意,文档还这样说:

然后使用 SHA-1 哈希将每个字符串转换为 GUID 算法。


这是我尝试做的,但我不确定我是否对某些概念或某些价值观有误,它不完整,而且我对 Guis 也有问题(用注释行解释):

Private Function GetHardwareId() As Guid

    Dim HardwareId As String = String.Empty

    Dim BIOSVersion, BIOSVendor, BIOSMajorRelease, BIOSMinorRelease,
        SystemManufacturer, SystemFamily, SystemProductName, SKUNumber As String

    ' Get System Info.
    Using wmi As New Management.ManagementObjectSearcher("select * from Win32_ComputerSystem")

        Using SystemInfo As Management.ManagementObject = wmi.Get(0)

            SystemManufacturer = Convert.ToString(SystemInfo.Properties("Manufacturer").Value)
            SystemProductName = Convert.ToString(SystemInfo.Properties("Model").Value)
            SystemFamily = I don't know how to get it.
            SKUNumber = I don't know how to get it.

        End Using

    End Using

    ' Get BIOS Info.
    Using wmi As New Management.ManagementObjectSearcher("select * from Win32_BIOS")

        Using BIOSInfo As Management.ManagementObject = wmi.Get(0)

            BIOSVersion = Convert.ToString(BIOSInfo.Properties("SMBIOSBIOSVersion").Value) 
            BIOSVendor = I don't know how to get it.
            BIOSMajorRelease = I don't know how to get it.
            BIOSMinorRelease = I don't know how to get it.

        End Using

    End Using ' wmi

    HardwareId = BIOSVersion & BIOSVendor & BIOSMajorRelease & BIOSMinorRelease &
                 SystemManufacturer & SystemFamily & SystemProductName & SKUNumber

    ' Here I call other method to encode the resulting string to SHA1 Hash
    HardwareId = ConvertToSHA1(HardwareId)
    ' and then continue below...

    ' But this will not work, 
    ' it throws an exception about missing "-" chars in the SHA1 string.
    ' So Microsoft formats "manualy" the SHA1 string to add some "-"?
    Return Guid.Parse(HardwareId)

End Function
.net vb.net wmi guid hardware-id
4个回答
2
投票

我不认为你的问题可以按照你想要的方式解决。 但目前还没有理由这么做。

MS 正在根据提供的各种数据的 SHA 哈希创建确定性 GUID。 如果根据rfc422标准创建,其中包括4个定义的GUID命名空间之一,我们应该能够使用这4个命名空间之一从相同的数据重新创建GUID。

但是,a) 我不能,b) MSDN 的“指定计算机的硬件 ID” 指出:

the hardware ID for the computer must be produced by the ComputerHardwareIds tool (ComputerHardwareIDs.exe)...
。 这让我相信他们使用专有方法(盐、私钥等)或定义自己的命名空间来生成这些。

您的次要/子问题的一些答案:

  • BIOS 版本/版本 - 根据 DTMF.org 规范,表 5“版本”位于偏移量 &H14 和 &H15 处,与“版本”不同。 但是,它们也可能嵌入到
    Win32_BIOS
    的名称、标题、描述和 SoftwareElementID 属性中(请参阅下面的工具)。 它似乎也隐藏在
    Win32_BIOS.BiosVersion(1)
    中,但它与名称/标题等相同。

我觉得有点奇怪,我们的系统相隔几年,但具有相同的 Release 值,它可能指的是 SMBios 版本/规范。

  • SKU:根据 MSDN,这又称为

    IdentificationCode

  • Family:显然是 BIOS 编码的一部分,但 WMI 尚未公开或返回它(还?)。

  • 产品名称也是如此,您从其他地方获取的

    Model
    可能只是巧合具有相同的值。

因此,哈希中使用的值似乎并没有全部暴露。 在我的旧系统上,Family 和 SKU 为空。 结果看起来第一个和第二个ID应该是一样的,但其实不是。

我不确定这些的用途是什么,或者如果 GUID/ID 只能从该工具获得,那么它们对普通应用程序有多大价值。您可以查看 SDK 的其他部分,看看是否有程序集等可以在运行时提供信息。

如果您只是想在下次看到某个系统或设备时识别它,您可以简单地基于 rfc422 编写自己的方法,以确保您定义的命名空间内的唯一值具有相同的“非常高的概率”。 像 MS 一样这样做的唯一原因是您是否希望看到该值来自其他地方,但事实并非如此。

最后,我没有费心发布 GUID 生成器,因为无论如何它都不会做你想要的事情。


WMI 帮助程序获取属性值:

Public Sub GetWMIInfo(wmiclass As String)

    Using searcher As New Management.ManagementObjectSearcher("select * from " & wmiclass)

        For Each item As System.Management.ManagementObject In searcher.Get
            DebugProperties(item)
        Next

    End Using
End Sub

' this sub is copied from the watcher answer I gave:
Private Sub DebugProperties(mo As Management.ManagementObject)

    For Each pd As PropertyData In mo.Properties
        If pd.Value IsNot Nothing Then
            ' some props are string arrays, so you can iterate them if you want

            Console.WriteLine("{0} {1}", pd.Name,
                              If(pd.Value IsNot Nothing,
                                 pd.Value.ToString,
                                 "Nothing"))
        End If

    Next
End Sub

输出是这样的:

Caption BIOS Date: XXXXXXXXXXXX Ver: 04.06.04
Description BIOS Date: ##/##/## 11:18:49 Ver: 04.06.04
Manufacturer Dell Inc.
Name BIOS Date: ##/##/## 11:18:49 Ver: 04.06.04
PrimaryBIOS True
ReleaseDate ########000000.000000+000
SerialNumber ######
SMBIOSBIOSVersion A##
SMBIOSMajorVersion #
SMBIOSMinorVersion #

1
投票

要生成相同的 GUID,您需要从 SMBIOS 获取值(通常使用 GetSystemFirmwareTable),然后使用“&”字符将它们连接起来。确保字符串使用 UTF-16 编码。然后,您需要使用类型 5 (SHA-1) UUID 生成方案,并将 70ffd812-4c7f-4c7d-0000-000000000000 作为命名空间。


1
投票
public ArrayList<String> getWinVendor()
        throws SecurityException, IOException,
        NullPointerException, IndexOutOfBoundsException,
        UnsupportedEncodingException {
    try {
        Process processProduct = Runtime.getRuntime().exec(new String[]{"wmic", "csproduct", "get", "vendor"});
        processProduct.getOutputStream().close();
        BufferedReader output = getOutput(processProduct);
        BufferedReader error = getError(processProduct);
        StringProductList = new ArrayList<String>();
        String line = "", result = "";
        while ((line = output.readLine()) != null) {
            if (!line.toLowerCase().startsWith("vendor") && line.length() > 0) {
                result = getSubStringSubstractEmptyAndTabSpace(line);
                if (result.length() > 0) {
                    StringProductList.add(result);
                } else {
                    StringProductList.add(UNKNOWN);
                }
            }
        }
        if (!StringProductList.isEmpty()) {
            return StringProductList;
        }
    } catch (Exception e) {
        if (e instanceof SecurityException
                || e instanceof IOException
                || e instanceof NullPointerException
                || e instanceof IndexOutOfBoundsException
                || e instanceof UnsupportedEncodingException) {
            e.printStackTrace();
        }
    }
    return null;
}

public BufferedReader getError(Process process) throws SecurityException, IOException,
        NullPointerException, IndexOutOfBoundsException, UnsupportedEncodingException {
    try {
        if (getCmdEncoding() != null) {
            return new BufferedReader(new InputStreamReader(process.getErrorStream(), "UTF-8"));
        }
    } catch (Exception e) {
        if (e instanceof SecurityException
                || e instanceof IOException
                || e instanceof NullPointerException
                || e instanceof IndexOutOfBoundsException) {
            e.printStackTrace();
        }
    }
    return new BufferedReader(new InputStreamReader(process.getErrorStream(), "UTF-8"));
}

public BufferedReader getOutput(Process process) throws SecurityException, IOException,
        NullPointerException, IndexOutOfBoundsException, UnsupportedEncodingException {
    try {
        if (getCmdEncoding() != null) {
            return new BufferedReader(new InputStreamReader(process.getInputStream(), "UTF-8"));
        }
    } catch (Exception e) {
        if (e instanceof SecurityException
                || e instanceof IOException
                || e instanceof NullPointerException
                || e instanceof IndexOutOfBoundsException) {
            e.printStackTrace();
        }
    }
    return new BufferedReader(new InputStreamReader(process.getInputStream(), "UTF-8"));
}

public static String getSubStringSubstractEmptyAndTabSpace(String word)
        throws NullPointerException, IndexOutOfBoundsException {
    if (word.length() > 0) {
        try {
            int length = word.length();
            int start = 0, end = length;
            for (int stringCharacter = 0; stringCharacter < length; stringCharacter++) {
                char c = word.charAt(stringCharacter);
                if (c == ' ' || c == '\t') {
                    start++;
                } else {
                    stringCharacter = length;
                }
            }
            for (int stringCharacter = length - 1; stringCharacter >= 0; stringCharacter--) {
                char c = word.charAt(stringCharacter);
                if (c == ' ' || c == '\t') {
                    end--;
                } else {
                    stringCharacter = -1;
                }
            }
            if (start == length) {
                return "";
            }
            if (end == 0) {
                return "";
            }
            if (start <= length - 1 && end >= 0) {
                return word.substring(start, end);
            }
        } catch (Exception e) {
            if (e instanceof NullPointerException
                    || e instanceof IndexOutOfBoundsException) {
                e.printStackTrace();
            }
        }
    }
    return word;
}

0
投票

我只是想分享我之前在 VB.NET 下完成的完整解决方案。

此代码复制与 computerhardwareids 程序完全相同的 HWID。请参阅 XML 文档块中的代码示例以获得相同的输出。

计算机硬件IdMicrosoftType.vb

''' <summary>
''' Specifies a Computer Hardware Id (CHID) for <see cref="UtilDevices.ComputerHardwareIdFromMicrosoftHwIdType"/> property.
''' </summary>
'''
''' <remarks>
''' <see href="https://docs.microsoft.com/en-us/windows-hardware/drivers/install/specifying-hardware-ids-for-a-computer"/>
''' <para></para>
''' Use <see cref="HardwareID_3"/> or <see cref="HardwareID_4"/> as the first choice 
''' if the software matches a computer that has a specific make, family, and model. 
''' This allows a software to match the specified computer, which provides the most precise metadata for the computer.
''' <para></para>
''' Use <see cref="HardwareID_5"/> as the second choice if the software covers the entire family of computers. 
''' In this case, the computer family is unique and is not branded with more than one product line.
''' <para></para>
''' Use <see cref="HardwareID_6"/> or <see cref="HardwareID_7"/> as the third choice 
''' if the software covers all of your computers or those computers with a specific enclosure type.
''' </remarks>
Public Enum ComputerHardwareIdMicrosoftType

    ''' <summary>
    ''' A hardwae Id. based on the following components: 
    ''' <list type="bullet">
    '''   <item>Manufacturer</item>
    ''' </list>
    ''' 
    ''' <para></para>
    ''' Example output from <c>computerhardwareids</c> program:
    ''' <list type="bullet">
    '''   <item>{035a20a6-fccf-5040-bc3e-b8b794c57f52} &lt;- Manufacturer</item>
    ''' </list>
    ''' </summary>
    HardwareID_14 = 14

    ''' <summary>
    ''' A hardwae Id. based on the following components: 
    ''' <list type="bullet">
    '''   <item>Manufacturer</item>
    '''   <item>Baseboard Manufacturer</item>
    '''   <item>Baseboard Product</item>
    ''' </list>
    ''' 
    ''' <para></para>
    ''' Example output from <c>computerhardwareids</c> program:
    ''' <list type="bullet">
    '''   <item>{53b44fbf-2036-56ac-bc21-722e871e765a} &lt;- Manufacturer + Baseboard Manufacturer + Baseboard Product</item>
    ''' </list>
    ''' </summary>
    HardwareID_13 = 13

    ''' <summary>
    ''' A hardwae Id. based on the following components: 
    ''' <list type="bullet">
    '''   <item>Manufacturer</item>
    '''   <item>Enclosure Type</item>
    ''' </list>
    ''' 
    ''' <para></para>
    ''' Example output from <c>computerhardwareids</c> program:
    ''' <list type="bullet">
    '''   <item>{a7aaa273-f280-513a-b907-919359a44175} &lt;- Manufacturer + Enclosure Type</item>
    ''' </list>
    ''' </summary>
    HardwareID_12 = 12

    ''' <summary>
    ''' A hardwae Id. based on the following components: 
    ''' <list type="bullet">
    '''   <item>Manufacturer</item>
    '''   <item>Family</item>
    ''' </list>
    ''' 
    ''' <para></para>
    ''' Example output from <c>computerhardwareids</c> program:
    ''' <list type="bullet">
    '''   <item>{7315e85a-f6ec-5bf0-b11d-411fb886c323} &lt;- Manufacturer + Family</item>
    ''' </list>
    ''' </summary>
    HardwareID_11 = 11

    ''' <summary>
    ''' A hardwae Id. based on the following components: 
    ''' <list type="bullet">
    '''   <item>Manufacturer</item>
    '''   <item>Family</item>
    '''   <item>Baseboard Manufacturer</item>
    '''   <item>Baseboard Product</item>
    ''' </list>
    ''' 
    ''' <para></para>
    ''' Example output from <c>computerhardwareids</c> program:
    ''' <list type="bullet">
    '''   <item>{a92d6619-1da8-577e-97af-b17ddbd71f75} &lt;- Manufacturer + Family + Baseboard Manufacturer + Baseboard Product</item>
    ''' </list>
    ''' </summary>
    HardwareID_10 = 10

    ''' <summary>
    ''' A hardwae Id. based on the following components: 
    ''' <list type="bullet">
    '''   <item>Manufacturer</item>
    '''   <item>Product Name</item>
    ''' </list>
    ''' 
    ''' <para></para>
    ''' Example output from <c>computerhardwareids</c> program:
    ''' <list type="bullet">
    '''   <item>{0dcce594-e561-59aa-9e30-21077acb429c} &lt;- Manufacturer + ProductName</item>
    ''' </list>
    ''' </summary>
    HardwareID_9 = 9

    ''' <summary>
    ''' A hardwae Id. based on the following components: 
    ''' <list type="bullet">
    '''   <item>Manufacturer</item>
    '''   <item>Product Name</item>
    '''   <item>Baseboard Manufacturer</item>
    '''   <item>Baseboard Product</item>
    ''' </list>
    ''' 
    ''' <para></para>
    ''' Example output from <c>computerhardwareids</c> program:
    ''' <list type="bullet">
    '''   <item>{8de62569-29ce-5767-84de-655c56d8ab67} &lt;- Manufacturer + ProductName + Baseboard Manufacturer + Baseboard Product</item>
    ''' </list>
    ''' </summary>
    HardwareID_8 = 8

    ''' <summary>
    ''' A hardwae Id. based on the following components: 
    ''' <list type="bullet">
    '''   <item>Manufacturer</item>
    '''   <item>SKU Number</item>
    ''' </list>
    ''' 
    ''' <para></para>
    ''' Example output from <c>computerhardwareids</c> program:
    ''' <list type="bullet">
    '''   <item>{d2957e9e-702e-591d-a829-36238d29d986} &lt;- Manufacturer + SKUNumber</item>
    ''' </list>
    ''' </summary>
    HardwareID_7 = 7

    ''' <summary>
    ''' A hardwae Id. based on the following components: 
    ''' <list type="bullet">
    '''   <item>Manufacturer</item>
    '''   <item>SKU Number</item>
    '''   <item>Baseboard Manufacturer</item>
    '''   <item>Baseboard Product</item>
    ''' </list>
    ''' 
    ''' <para></para>
    ''' Example output from <c>computerhardwareids</c> program:
    ''' <list type="bullet">
    '''   <item>{3b4375dd-3630-5839-9362-85b2bdb9defb} &lt;- Manufacturer + SKUNumber + Baseboard Manufacturer + Baseboard Product</item>
    ''' </list>
    ''' </summary>
    HardwareID_6 = 6

    ''' <summary>
    ''' A hardwae Id. based on the following components: 
    ''' <list type="bullet">
    '''   <item>Manufacturer</item>
    '''   <item>Family</item>
    '''   <item>Product Name</item>
    ''' </list>
    ''' 
    ''' <para></para>
    ''' Example output from <c>computerhardwareids</c> program:
    ''' <list type="bullet">
    '''   <item>{ceb119e2-5411-5694-a8f1-57a5767fe85d} &lt;- Manufacturer + Family + ProductName</item>
    ''' </list>
    ''' </summary>
    HardwareID_5 = 5

    ''' <summary>
    ''' A hardwae Id. based on the following components: 
    ''' <list type="bullet">
    '''   <item>Manufacturer</item>
    '''   <item>Family</item>
    '''   <item>Product Name</item>
    '''   <item>SKU Number</item>
    ''' </list>
    ''' 
    ''' <para></para>
    ''' Example output from <c>computerhardwareids</c> program:
    ''' <list type="bullet">
    '''   <item>{9b3edbb4-9a86-5379-ad5e-4c6df298d9f8} &lt;- Manufacturer + Family + ProductName + SKUNumber</item>
    ''' </list>
    ''' </summary>
    HardwareID_4 = 4

    ''' <summary>
    ''' A hardwae Id. based on the following components: 
    ''' <list type="bullet">
    '''   <item>Manufacturer</item>
    '''   <item>Family</item>
    '''   <item>Product Name</item>
    '''   <item>SKU Number</item>
    '''   <item>Baseboard Manufacturer</item>
    '''   <item>Baseboard Product</item>
    ''' </list>
    ''' 
    ''' <para></para>
    ''' Example output from <c>computerhardwareids</c> program:
    ''' <list type="bullet">
    '''   <item>{618e64e8-ca25-5b1a-b1ee-b66a7385f1ed} &lt;- Manufacturer + Family + ProductName + SKUNumber + Baseboard Manufacturer + Baseboard Product</item>
    ''' </list>
    ''' </summary>
    HardwareID_3 = 3

    ''' <summary>
    ''' A hardwae Id. based on the following components: 
    ''' <list type="bullet">
    '''   <item>Manufacturer</item>
    '''   <item>Product Name</item>
    '''   <item>BIOS Vendor</item>
    '''   <item>BIOS Version</item>
    '''   <item>BIOS Major Release</item>
    '''   <item>BIOS Minor Release</item>
    ''' </list>
    ''' 
    ''' <para></para>
    ''' Example output from <c>computerhardwareids</c> program:
    ''' <list type="bullet">
    '''   <item>{dfed620c-3091-5ce9-bf23-2d47ba155d65} &lt;- Manufacturer + ProductName + BIOS Vendor + BIOS Version + BIOS Major Release + BIOS Minor Release</item>
    ''' </list>
    ''' </summary>
    HardwareID_2 = 2

    ''' <summary>
    ''' A hardwae Id. based on the following components: 
    ''' <list type="bullet">
    '''   <item>Manufacturer</item>
    '''   <item>Family</item>
    '''   <item>Product Name</item>
    '''   <item>BIOS Vendor</item>
    '''   <item>BIOS Version</item>
    '''   <item>BIOS Major Release</item>
    '''   <item>BIOS Minor Release</item>
    ''' </list>
    ''' 
    ''' <para></para>
    ''' Example output from <c>computerhardwareids</c> program:
    ''' <list type="bullet">
    '''   <item>{9b8fcb39-4611-5c0c-a947-4c269fb3b9e9} &lt;- Manufacturer + Family + ProductName + BIOS Vendor + BIOS Version + BIOS Major Release + BIOS Minor Release</item>
    ''' </list>
    ''' </summary>
    HardwareID_1 = 1

    ''' <summary>
    ''' A hardwae Id. based on the following components: 
    ''' <list type="bullet">
    '''   <item>Manufacturer</item>
    '''   <item>Family</item>
    '''   <item>Product Name</item>
    '''   <item>SKU Number</item>
    '''   <item>BIOS Vendor</item>
    '''   <item>BIOS Version</item>
    '''   <item>BIOS Major Release</item>
    '''   <item>BIOS Minor Release</item>
    ''' </list>
    ''' 
    ''' <para></para>
    ''' Example output from <c>computerhardwareids</c> program:
    ''' <list type="bullet">
    '''   <item>{d669d1f2-9fcc-580d-bee1-a7ec7078d827} &lt;- Manufacturer + Family + ProductName + SKUNumber + BIOS Vendor + BIOS Version + BIOS Major Release + BIOS Minor Release</item>
    ''' </list>
    ''' </summary>
    HardwareID_0 = 0

End Enum

GetComputerHardwareIdFromMicrosoftHwIdType 方法

''' <summary>
''' Gets a unique computer hardware identifier (CHID) that matches the current computer.
''' <para></para>
''' This identifier is generated following Microsoft's PC Device Metadata packages schemas:
''' <para></para>
''' https://docs.microsoft.com/en-us/windows-hardware/drivers/install/specifying-hardware-ids-for-a-computer
''' <para></para>
''' In fact, this function generates the exact same identifiers as the 
''' 'computerhardwareids.exe' program included in the Windows SDK:
''' https://docs.microsoft.com/es-es/windows-hardware/drivers/devtest/computerhardwareids
''' <para></para>
''' https://developer.microsoft.com/en-us/windows/downloads/sdk-archive/
''' <para></para>
''' <para></para>
''' Use HardwareID-3 or HardwareID-4 as the first choice if the software matches a computer 
''' that has a specific make, family, and model. This allows a software to match the specified computer, 
''' which provides the most precise metadata for the computer.
''' <para></para>
''' Use HardwareID-5, as the second choice if the software covers the entire family of computers. 
''' In this case, the computer family is unique and is not branded with more than one product line.
''' <para></para>
''' Use HardwareID-6 or HardwareID-7 as the third choice if the software covers all of your computers 
''' or those computers with a specific enclosure type.
''' </summary>
'''
''' <example> This is a code example.
''' <code language="VB.NET">
''' Console.WriteLine($"{{{GetComputerHardwareIdFromMicrosoftHwIdType(ComputerHardwareIdMicrosoftType.HardwareID_0)}}}    &lt;- Manufacturer + Family + ProductName + SKUNumber + BIOS Vendor + BIOS Version + BIOS Major Release + BIOS Minor Release")
''' Console.WriteLine($"{{{GetComputerHardwareIdFromMicrosoftHwIdType(ComputerHardwareIdMicrosoftType.HardwareID_1)}}}    &lt;- Manufacturer + Family + ProductName + BIOS Vendor + BIOS Version + BIOS Major Release + BIOS Minor Release")
''' Console.WriteLine($"{{{GetComputerHardwareIdFromMicrosoftHwIdType(ComputerHardwareIdMicrosoftType.HardwareID_2)}}}    &lt;- Manufacturer + ProductName + BIOS Vendor + BIOS Version + BIOS Major Release + BIOS Minor Release")
''' Console.WriteLine($"{{{GetComputerHardwareIdFromMicrosoftHwIdType(ComputerHardwareIdMicrosoftType.HardwareID_3)}}}    &lt;- Manufacturer + Family + ProductName + SKUNumber + Baseboard Manufacturer + Baseboard Product")
''' Console.WriteLine($"{{{GetComputerHardwareIdFromMicrosoftHwIdType(ComputerHardwareIdMicrosoftType.HardwareID_4)}}}    &lt;- Manufacturer + Family + ProductName + SKUNumber")
''' Console.WriteLine($"{{{GetComputerHardwareIdFromMicrosoftHwIdType(ComputerHardwareIdMicrosoftType.HardwareID_5)}}}    &lt;- Manufacturer + Family + ProductName")
''' Console.WriteLine($"{{{GetComputerHardwareIdFromMicrosoftHwIdType(ComputerHardwareIdMicrosoftType.HardwareID_6)}}}    &lt;- Manufacturer + SKUNumber + Baseboard Manufacturer + Baseboard Product")
''' Console.WriteLine($"{{{GetComputerHardwareIdFromMicrosoftHwIdType(ComputerHardwareIdMicrosoftType.HardwareID_7)}}}    &lt;- Manufacturer + SKUNumber")
''' Console.WriteLine($"{{{GetComputerHardwareIdFromMicrosoftHwIdType(ComputerHardwareIdMicrosoftType.HardwareID_8)}}}    &lt;- Manufacturer + ProductName + Baseboard Manufacturer + Baseboard Product")
''' Console.WriteLine($"{{{GetComputerHardwareIdFromMicrosoftHwIdType(ComputerHardwareIdMicrosoftType.HardwareID_9)}}}    &lt;- Manufacturer + ProductName")
''' Console.WriteLine($"{{{GetComputerHardwareIdFromMicrosoftHwIdType(ComputerHardwareIdMicrosoftType.HardwareID_10)}}}    &lt;- Manufacturer + Family + Baseboard Manufacturer + Baseboard Product")
''' Console.WriteLine($"{{{GetComputerHardwareIdFromMicrosoftHwIdType(ComputerHardwareIdMicrosoftType.HardwareID_11)}}}    &lt;- Manufacturer + Family")
''' Console.WriteLine($"{{{GetComputerHardwareIdFromMicrosoftHwIdType(ComputerHardwareIdMicrosoftType.HardwareID_12)}}}    &lt;- Manufacturer + Enclosure Type")
''' Console.WriteLine($"{{{GetComputerHardwareIdFromMicrosoftHwIdType(ComputerHardwareIdMicrosoftType.HardwareID_13)}}}    &lt;- Manufacturer + Baseboard Manufacturer + Baseboard Product")
''' Console.WriteLine($"{{{GetComputerHardwareIdFromMicrosoftHwIdType(ComputerHardwareIdMicrosoftType.HardwareID_14)}}}    &lt;- Manufacturer")
''' </code>
''' </example>
'''
''' <returns>
''' The resulting unique computer hardware identifier (CHID) that matches the current computer.
''' </returns>
<DebuggerStepThrough>
Private Shared Function GetComputerHardwareIdFromMicrosoftHwIdType(hwidType As ComputerHardwareIdMicrosoftType) As Guid

    Select Case CInt(hwidType)
        Case Is < ComputerHardwareIdMicrosoftType.HardwareID_0, Is > ComputerHardwareIdMicrosoftType.HardwareID_14
            Throw New InvalidEnumArgumentException(argumentName:=NameOf(hwidType), invalidValue:=hwidType, enumClass:=GetType(ComputerHardwareIdMicrosoftType))
    End Select

    ' Namespace used by 'computerhardwareids.exe' program included in the Windows SDK.
    ' https://stackoverflow.com/questions/25190906/get-hardware-ids-like-microsoft-does/43619888#43619888
    ' https://blogs.gnome.org/hughsie/2017/04/25/reverse-engineering-computerhardwareids-exe-with-winedbg/
    Dim namespaceUUID As Guid = Guid.Parse("70ffd812-4c7f-4c7d-0000-000000000000")

    ' Win32_ComputerSystem fields
    Dim manufacturer, family, productName, skuNumber As String

    ' Win32_BaseBoard fields
    Dim baseBoardManufacturer, baseBoardProduct As String

    ' Win32_BIOS fields
    Dim biosVendor, biosVersion, biosMajorRelease, biosMinorRelease As String

    ' Win32_SystemEnclosure fields
    Dim enclosureType As String = Nothing

    ' Retrieve computer info.
    Using mos As New ManagementObjectSearcher()

        ' Win32_ComputerSystem
        mos.Query.QueryString = "SELECT Manufacturer,Model,SystemFamily,SystemSKUNumber FROM Win32_ComputerSystem"
        Using systemInfo As ManagementObject = DirectCast(mos.Get(0), ManagementObject)
            manufacturer = CStr(systemInfo.Properties("Manufacturer")?.Value)?.Trim()
            productName = CStr(systemInfo.Properties("Model")?.Value)?.Trim()
            family = CStr(systemInfo.Properties("SystemFamily")?.Value)?.Trim()
            skuNumber = CStr(systemInfo.Properties("SystemSKUNumber")?.Value)?.Trim()
        End Using

        ' Win32_BaseBoard
        mos.Query.QueryString = "SELECT Manufacturer,Product FROM Win32_BaseBoard"
        Using baseBoardInfo As ManagementObject = DirectCast(mos.Get(0), ManagementObject)
            baseBoardManufacturer = CStr(baseBoardInfo.Properties("Manufacturer")?.Value)?.Trim()
            baseBoardProduct = CStr(baseBoardInfo.Properties("Product")?.Value)?.Trim()
        End Using

        ' Win32_BIOS
        mos.Query.QueryString = "SELECT Manufacturer,SMBIOSBIOSVersion,SystemBiosMajorVersion,SystemBiosMinorVersion FROM Win32_BIOS"
        Using biosInfo As ManagementObject = DirectCast(mos.Get(0), ManagementObject)
            biosVendor = CStr(biosInfo.Properties("Manufacturer")?.Value)?.Trim()
            biosVersion = CStr(biosInfo.Properties("SMBIOSBIOSVersion")?.Value)?.Trim()
            biosMajorRelease = CByte(biosInfo.Properties("SystemBiosMajorVersion")?.Value).ToString("X2").ToLower()
            biosMinorRelease = CByte(biosInfo.Properties("SystemBiosMinorVersion")?.Value).ToString("X2").ToLower()
        End Using

        ' Win32_SystemEnclosure
        mos.Query.QueryString = "SELECT ChassisTypes FROM Win32_SystemEnclosure"
        Using enclosureInfo As ManagementObject = DirectCast(mos.Get(0), ManagementObject)
            Dim chassisTypes As UShort() = DirectCast(enclosureInfo.Properties("ChassisTypes").Value, UShort())
            For Each chassisType As UShort In chassisTypes
                enclosureType &= CStr(chassisType)
            Next chassisType
            If String.IsNullOrEmpty(enclosureType) Then
                enclosureType = "2" ' Unknown (2)
            End If
        End Using

    End Using

#If DEBUG Then
    ' Console.WriteLine($"{NameOf(manufacturer)}          = {manufacturer}")
    ' Console.WriteLine($"{NameOf(enclosureType)}         = {enclosureType}")
    ' Console.WriteLine($"{NameOf(productName)}           = {productName}")
    ' Console.WriteLine($"{NameOf(family)}                = {family}")
    ' Console.WriteLine($"{NameOf(skuNumber)}             = {skuNumber}")
    ' Console.WriteLine($"{NameOf(baseBoardManufacturer)} = {baseBoardManufacturer}")
    ' Console.WriteLine($"{NameOf(baseBoardProduct)}      = {baseBoardProduct}")
    ' Console.WriteLine($"{NameOf(biosVendor)}            = {biosVendor}")
    ' Console.WriteLine($"{NameOf(biosVersion)}           = {biosVersion}")
    ' Console.WriteLine($"{NameOf(biosMajorRelease)}      = {biosMajorRelease}")
    ' Console.WriteLine($"{NameOf(biosMinorRelease)}      = {biosMinorRelease}")
#End If

    Dim stringToHash As String = String.Empty

    Select Case hwidType

        Case ComputerHardwareIdMicrosoftType.HardwareID_0
            stringToHash = $"{manufacturer}&{family}&{productName}&{skuNumber}&{biosVendor}&{biosVersion}&{biosMajorRelease}&{biosMinorRelease}"

        Case ComputerHardwareIdMicrosoftType.HardwareID_1
            stringToHash = $"{manufacturer}&{family}&{productName}&{biosVendor}&{biosVersion}&{biosMajorRelease}&{biosMinorRelease}"

        Case ComputerHardwareIdMicrosoftType.HardwareID_2
            stringToHash = $"{manufacturer}&{productName}&{biosVendor}&{biosVersion}&{biosMajorRelease}&{biosMinorRelease}"

        Case ComputerHardwareIdMicrosoftType.HardwareID_3
            stringToHash = $"{manufacturer}&{family}&{productName}&{skuNumber}&{baseBoardManufacturer}&{baseBoardProduct}"

        Case ComputerHardwareIdMicrosoftType.HardwareID_4
            stringToHash = $"{manufacturer}&{family}&{productName}&{skuNumber}"

        Case ComputerHardwareIdMicrosoftType.HardwareID_5
            stringToHash = $"{manufacturer}&{family}&{productName}"

        Case ComputerHardwareIdMicrosoftType.HardwareID_6
            stringToHash = $"{manufacturer}&{skuNumber}&{baseBoardManufacturer}&{baseBoardProduct}"

        Case ComputerHardwareIdMicrosoftType.HardwareID_7
            stringToHash = $"{manufacturer}&{skuNumber}"

        Case ComputerHardwareIdMicrosoftType.HardwareID_8
            stringToHash = $"{manufacturer}&{productName}&{baseBoardManufacturer}&{baseBoardProduct}"

        Case ComputerHardwareIdMicrosoftType.HardwareID_9
            stringToHash = $"{manufacturer}&{productName}"

        Case ComputerHardwareIdMicrosoftType.HardwareID_10
            stringToHash = $"{manufacturer}&{family}&{baseBoardManufacturer}&{baseBoardProduct}"

        Case ComputerHardwareIdMicrosoftType.HardwareID_11
            stringToHash = $"{manufacturer}&{family}"

        Case ComputerHardwareIdMicrosoftType.HardwareID_12
            stringToHash = $"{manufacturer}&{enclosureType}"

        Case ComputerHardwareIdMicrosoftType.HardwareID_13
            stringToHash = $"{manufacturer}&{baseBoardManufacturer}&{baseBoardProduct}"

        Case ComputerHardwareIdMicrosoftType.HardwareID_14
            stringToHash = manufacturer

    End Select

    ' Creates a name-based UUID using the algorithm from RFC 4122 §4.3.
    ' https://stackoverflow.com/questions/61267254/generating-uuid-based-on-strings
    Dim generateGuidDelegate As Func(Of Guid, String, Guid) =
        Function(namespaceId As Guid, name As String) As Guid

            ' Converts a GUID (expressed as a byte array) to/from network order (MSB-first).
            Dim swapByteOrderDelegate As New Action(Of Byte())(
                Sub(guid() As Byte)
                    Dim temp As Byte = guid(0)
                    guid(0) = guid(3)
                    guid(3) = temp

                    temp = guid(1)
                    guid(1) = guid(2)
                    guid(2) = temp

                    temp = guid(4)
                    guid(4) = guid(5)
                    guid(5) = temp

                    temp = guid(6)
                    guid(6) = guid(7)
                    guid(7) = temp
                End Sub)

            ' Convert the name to a sequence of octets (as defined by the standard or conventions of its namespace) (step 3).
            Dim nameBytes() As Byte = Encoding.Unicode.GetBytes(name)

            ' Convert the namespace UUID to network order (step 3).
            Dim namespaceBytes() As Byte = namespaceId.ToByteArray()
            swapByteOrderDelegate.Invoke(namespaceBytes)

            ' Compute the hash of the name space ID concatenated with the name (step 4).
            Dim hash As Byte()
            Using algorithm As HashAlgorithm = SHA1.Create()
                algorithm.TransformBlock(namespaceBytes, 0, namespaceBytes.Length, Nothing, 0)
                algorithm.TransformFinalBlock(nameBytes, 0, nameBytes.Length)
                hash = algorithm.Hash
            End Using

            ' Most bytes from the hash are copied straight to the bytes of the new GUID (steps 5-7, 9, 11-12).
            Dim newGuid(15) As Byte
            Array.Copy(hash, 0, newGuid, 0, 16)

            ' Set the four most significant bits (bits 12 through 15) of the time_hi_and_version field
            ' to the appropriate 4-bit version number from Section 4.1.3 (step 8).
            newGuid(6) = CByte((newGuid(6) And &HF) Or (5 << 4))

            ' Set the two most significant bits (bits 6 and 7) of the clock_seq_hi_and_reserved
            ' to zero and one, respectively (step 10).
            newGuid(8) = CByte((newGuid(8) And &H3F) Or &H80)

            ' Convert the resulting UUID to local byte order (step 13).
            swapByteOrderDelegate.Invoke(newGuid)
            Return New Guid(newGuid)
        End Function

    Return generateGuidDelegate.Invoke(namespaceUUID, stringToHash)

End Function
© www.soinside.com 2019 - 2024. All rights reserved.