Previous iterations of Windows 10 have the HardwareToken
API (aka ASHWID) to get a unique identifier for the device, but it had several drawbacks:
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)
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:
userSystemInfo
Restricted Capability
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.
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
.
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).