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).