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

Posted

技术标签:

【中文标题】如何获取在 C# 中运行 Windows 8 的机器的唯一标识符?【英文标题】:How do I get a unique identifier for a machine running Windows 8 in C#? 【发布时间】:2012-09-13 17:42:36 【问题描述】:

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

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

问题是,我如何把那个 IBuffer 变成我可以使用的字符串?

【问题讨论】:

引用:However, the ASHWID changes if the hardware profile of the device changes, such as when the user unplugs a USB Bluetooth adapter。 msdn.microsoft.com/en-us/library/windows/apps/jj553431.aspx 我确实注意到了这一点,但它似乎是 Windows 8 中可用的最佳选择。对于我们的使用来说,即使它不如我们习惯的那么好,它也足够了! :) 【参考方案1】:

经过大量寻找实际上是在 JS 或 C++ 中的建议后,我终于找到了答案!

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

【讨论】:

请注意,这个 id 不是恒定的!如果你打开飞行模式,你会得到一个不同的 ID。 @ThomasLevesque 我相信您对硬件进行更改时的 id 转移是正确的,但我刚刚尝试过(Win10 中的 UWP)并且在打开或关闭飞行模式以及何时获得相同的值我拔掉了鼠标,所以它看起来不像你在这里所说的那么敏感,至少在这个平台上是这样。 @ruffin,我注意到在 WinRT 中,它可能在 UWP 中发生了变化 如果您将互联网连接从 Wi-Fi 切换到以太网或相反,此 token.Id 值会发生变化。所以,它不是独一无二的。至少在 Win 8.1 中【参考方案2】:

这应该也可以,但我没有要测试的 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()”方法。 好吧,如果我将您的第一个建议复制/粘贴到我的项目中,我会收到此错误:“Windows.Storage.Streams.IBuffer”不包含“ToArray”的定义并且没有扩展方法“ToArray” ' 可以找到接受“Windows.Storage.Streams.IBuffer”类型的第一个参数。 您需要添加适当的 using 语句 - using System.Runtime.InteropServices.WindowsRuntime 并且您必须拥有 .NET 4.5 添加 using 语句似乎确实有效,但有点奇怪的是,Visual Studio 不想建议像通常在我键入需要新 using 语句的内容时那样解决问题! @StarlitSkies - 我发现 VS2010 中不建议扩展,例如 Linq 扩展。【参考方案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。根据您的具体需求,这可能是一个更好的解决方案。

【讨论】:

【参考方案4】:

对于 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 作为您的机器标识符。在下一次运行时,从文件中获取它。见msdn.microsoft.com/en-us/library/system.guid.newguid.aspx

以上是关于如何获取在 C# 中运行 Windows 8 的机器的唯一标识符?的主要内容,如果未能解决你的问题,请参考以下文章

如何获取方法异步 c# windows phone 8.1 的值

如何在 UWP 应用(C# 或 WinJS)中获取 Windows 10 版本(例如 1809、1903、1909、...)?

.NET Framework 4 桌面应用程序 [C#] 将运行 Windows 8、8.1 和 10

在 Parallels 8 中的 Windows 7 上运行 C# Windows Forms 应用程序错误

如何从 SessionID 获取 Windows 用户名?

在 C# 中,如何在 Windows 10 的“区域和语言”下选择“国家或地区”?