How to get unique Device IDs on Windows 10 Anniversary Update

Peter Torr - MSFT picture Peter Torr - MSFT · Nov 2, 2016 · Viewed 7.9k times · Source

Previous iterations of Windows 10 have the HardwareToken API (aka ASHWID) to get a unique identifier for the device, but it had several drawbacks:

  • It was only available on Desktop and Mobile platforms, which required you to add an Extension SDK to your project (and wasn't available on HoloLens or other platforms)
  • On the PC, the value could "drift" as hardware changed (even just plugging a laptop into a docking station would change the ID), so you needed complex backend logic to correlate device IDs
  • The value was specific to a single app, and couldn't be shared across apps by the same publisher

Is there a new way in the Anniversary Update to get a more useful / stable ID that's consistent across all Windows 10 platforms? I want to use the ID in my apps to correlate telemetry from the same device for purposes of usage metrics and advertising. I will not use the value for identifying the user, creating anonymous accounts, encrypting data, or anything else like that. It will only be used for telemetry purposes.

I want to do something like:

var id = Windows.Something.GetDeviceId();  // hypothetical OS function
var telemetry = MyApp.GetUsageTelemetry(); // my own function

// Use (eg) HttpClient to send both id and telemetry to my 
// cloud infrastructure for processing and correlation
SendDataToCloudForProcessing(id, telemetry)

Answer

Peter Torr - MSFT picture Peter Torr - MSFT · Nov 2, 2016

Updated Nov 3rd 2017 (new Registry value, below)

The Windows 10 Anniversary Update introduced the new SystemIdentification type which does exactly what you want. It has several benefits over the old ASHWID:

  • It is available on all Windows 10 platforms
    • Note: The ASHWID is now also available on all platforms, but still has the other drawbacks listed above
  • It returns a stable value (even on PCs) that will not change due to hardware upgrades or re-installations of the OS
  • It returns a value that is the same for all apps by the same publisher, allowing correlation across your portfolio of apps
  • It can also return a value that is the same across all apps, for a specific user, if you have the userSystemInfo Restricted Capability
    • Note: This is most useful for Enterprise scenarios; you are unlikely to have an app approved for the Windows Store that uses this feature without a very good justification, since it represents a privacy concern

There is one minor drawback to the API: it won't work on some old PCs, since it requires either UEFI or a TPM. Most PCs built in the last 5+ years should have this hardware, and all other non-PC devices (phone, Xbox, HoloLens, etc.) have the correct hardware. If you find a PC that doesn't have the hardware, you will need to fall back to the ASHWID or some other mechanism.

Update Nov 3 2017

Starting with the Windows Fall Creator's Update (aka 1709 or RS3 or Universal API Contract 5) there is a new Registry identification source which provides a relatively stable ID in case the user doesn't have appropriate hardware. It will change if the user does a fresh re-install of the OS (not an upgrade, but a new install) or if the user changes the registry, but otherwise has the same benefits as Uefi or Tmp.

End update Nov 3 2017

Using the API is simple; there is no need for complex parsing or accounting for drift on the back-end:

using Windows.System.Profile;

IBuffer GetSystemId()
{
  // This sample gets the publisher ID which is the same for all apps
  // by this publisher on this device.
  // Use GetSystemIdForUser if you have the userSystemId capability
  // and need the same ID across all apps for this user (not 
  // really applicable for apps in the Windows Store)
  var systemId = SystemIdentification.GetSystemIdForPublisher();

  // Make sure this device can generate the IDs
  if (systemId.Source != SystemIdentificationSource.None)
  {
    // The Id property has a buffer with the unique ID
    return systemId.Id;
  }

  // This is a very old PC without the correct hardware. Use 
  // another mechanism to generate an ID (or perhaps just give 
  // up due to the small number of people that won't have the ID; 
  // depends on your business needs).
  return GetIdFromAshwidOrSomethingElse();
}

As noted in the question, this ID should only be used for purposes of correlation in a back-end service (eg, for telemetry, advertising, usage metrics, etc.). It should never be used to create anonymous user accounts, to identify or track users, to encrypt user data, etc. This is because different users can share the same device, or the same user can roam across different devices, so the ID doesn't map 1:1 with a user or their data.

This API is available in the Universal API Contract v3, and can be found in the Windows Universal SDK version 10.0.14393.0 (remember that if you're doing multi-version apps and want to light-up usage of this API, you should not do runtime version check; instead you should just query the OS to see if the API is available).