如何在C#中获取运行Windows 8的计算机的唯一标识符?

8

我正在开发一款使用C#编写的Metro应用程序,需要一种唯一识别设备的方法。我在文档中找到了ASHWID,看起来很棒。建议使用的代码如下:

HardwareToken token = HardwareIdentification.GetPackageSpecificToken(null);
IBuffer hardwareId = token.Id;
IBuffer signature = token.Signature;
IBuffer certificate = token.Certificate;

问题在于,我该如何将IBuffer转换为字符串以便使用?

1
然而,如果设备的硬件配置文件发生更改,例如用户拔下USB蓝牙适配器,则ASHWID会发生变化。http://msdn.microsoft.com/en-us/library/windows/apps/jj553431.aspx - Hans Passant
我确实注意到了,但似乎这是Windows 8中可用的最佳选项。对于我们的用途来说,即使它不如我们习惯的那样好,也足够了! :) - StarlitSkies
4个回答

15

经过长时间寻找,我终于找到一个答案!

private string GetHardwareId()  
{  
    var token = HardwareIdentification.GetPackageSpecificToken(null);  
    var hardwareId = token.Id;  
    var dataReader = Windows.Storage.Streams.DataReader.FromBuffer(hardwareId);  

    byte[] bytes = new byte[hardwareId.Length];  
    dataReader.ReadBytes(bytes);  

    return BitConverter.ToString(bytes);  
}  

感谢此博客 - http://bartwullems.blogspot.co.uk/2012/09/windows-8-uniquely-identifying-device.html


6
请注意,此ID 不是恒定的!如果您打开飞行模式,将会得到一个不同的ID。 - Thomas Levesque
@ThomasLevesque 我相信您关于硬件更改时ID会发生移位的说法是正确的,但我刚刚尝试了(在Win10中的UWP),并且在打开或关闭飞行模式以及拔掉鼠标时都得到了相同的值,因此在这个平台上它似乎没有您所声称的那么敏感。 - ruffin
@ruffin,我注意到在WinRT中,可能会在UWP中有所改变。 - Thomas Levesque
如果您从Wi-Fi切换到以太网或相反,此token.Id值将发生更改。因此,它不是唯一的。至少在Win 8.1中是这样。 - Heshan

4

这也应该可以工作,但我没有Windows 8进行测试...

private string GetHardwareId()   
{ 
  return BitConverter.ToString(Windows.System.Profile.HardwareIdentification.GetPackageSpecificToken(null).Id.ToArray());
}

如果你需要多次调用它,你可能需要将它放在一个Lazy<T>中。

private static Lazy<string> _hardwareId = new Lazy<string>(() => BitConverter.ToString(Windows.System.Profile.HardwareIdentification.GetPackageSpecificToken(null).Id.ToArray()), true);

public string HardwareId()   
{ 
     return _hardwareId.Value;
}

如果您知道它将始终被调用,可以将其设置为静态:

public static readonly string HardwareId = BitConverter.ToString(Windows.System.Profile.HardwareIdentification.GetPackageSpecificToken(null).Id.ToArray()));

唉,"Windows.System.Profile.HardwareIdentification.GetPackageSpecificToken(null).Id.ToArray()" 不起作用 - 在 Windows 8 中的 IBuffer 上没有 "ToArray()" 方法。 - StarlitSkies
好的,如果我将您的第一个建议复制/粘贴到我的项目中,我会得到以下错误:“Windows.Storage.Streams.IBuffer”不包含“ToArray”的定义,也没有接受类型为“Windows.Storage.Streams.IBuffer”的第一个参数的扩展方法“ToArray”可以找到。 - StarlitSkies
1
你需要添加适当的using语句 - using System.Runtime.InteropServices.WindowsRuntime,并且你必须拥有.NET 4.5。 - Chris Gessler
如果您使用此方法,当设备通过USB或蓝牙添加时,硬件ID可能会发生变化。请按照我的答案中所述的方式过滤信息。 - Kris Vandermotten
@KrisVandermotten - 很好注意到了,不过问题是如何将结果转换为字符串。 - Chris Gessler
显示剩余2条评论

3
您可以使用HardwareIdentification.GetPackageSpecificToken(null),参见http://msdn.microsoft.com/en-us/library/windows/apps/jj553431.aspx。该函数提供了许多信息,您可以根据需要进行筛选。例如:
public static string GetMachineId()
{
    var hardwareToken = 
        HardwareIdentification.GetPackageSpecificToken(null).Id.ToArray();
    var count = hardwareToken.Length / 4;
    ulong id = 0ul;
    for (int i = 0; i < count; i++)
    {
        switch (BitConverter.ToUInt16(hardwareToken, i * 4))
        {
            case 1:
                // processor
            case 2:
                // memory
            case 9:
                // system BIOS
                id = (id << 12) ^ BitConverter.ToUInt16(hardwareToken, i * 4 + 2);
                break;
        }
    }
    return Convert.ToBase64String(BitConverter.GetBytes(id));
}

然而,请记住此函数及其底层API不能保证在连接到互联网的所有计算机上实现绝对唯一性。您通常需要结合用户信息使用此功能。

另一个选项是在本地(非漫游)存储中生成和存储GUID,并将其用作您的机器ID。根据您确切的需求,这可能是更好的解决方案。


0

如果你想要一个GUID ID,你可以按照上面的答案进行扩展。

    private Guid GetHardwareId()
    {
        var token = HardwareIdentification.GetPackageSpecificToken(null);  
        var hardwareId = token.Id;  
        var dataReader = Windows.Storage.Streams.DataReader.FromBuffer(hardwareId);  

        byte[] bytes = new byte[hardwareId.Length];  
        dataReader.ReadBytes(bytes);  

        byte[] deviceId = new byte[16];
        Array.Copy((byte[])bytes, deviceId, deviceId.Length);

        return new Guid(deviceId);
    }

那听起来不是个好主意。我的意思是:在本地存储中查找文件。如果(且仅当)没有找到该文件,则创建一个新的Guid并将其放入其中,使用Guid.NewGuid()创建。使用该Guid作为您的机器标识符。在下一次运行时,从文件中获取它。请参阅https://msdn.microsoft.com/en-us/library/system.guid.newguid.aspx。 - Kris Vandermotten

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接