Skip to content

Commit a97a233

Browse files
marcpopMSFTgithub-actions
authored andcommitted
Add Dev Device ID
1 parent 3f6b260 commit a97a233

File tree

3 files changed

+126
-0
lines changed

3 files changed

+126
-0
lines changed
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using Microsoft.Win32;
5+
6+
namespace Microsoft.DotNet.Cli.Telemetry
7+
{
8+
internal static class DeviceIdGetter
9+
{
10+
public static string GetDeviceId()
11+
{
12+
string deviceId = GetCachedDeviceId();
13+
14+
// Check if the device Id is already cached
15+
if (string.IsNullOrEmpty(deviceId))
16+
{
17+
// Generate a new guid
18+
deviceId = Guid.NewGuid().ToString("D").ToLowerInvariant();
19+
20+
// Cache the new device Id
21+
CacheDeviceId(deviceId);
22+
}
23+
24+
return deviceId;
25+
}
26+
27+
private static string GetCachedDeviceId()
28+
{
29+
string deviceId = null;
30+
31+
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
32+
{
33+
// Get device Id from Windows registry
34+
using (var key = Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Microsoft\DeveloperTools"))
35+
{
36+
deviceId = key?.GetValue("deviceid") as string;
37+
}
38+
}
39+
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
40+
{
41+
// Get device Id from Linux cache file
42+
string cacheFilePath;
43+
string xdgCacheHome = Environment.GetEnvironmentVariable("XDG_CACHE_HOME");
44+
if (!string.IsNullOrEmpty(xdgCacheHome))
45+
{
46+
cacheFilePath = Path.Combine(xdgCacheHome, "Microsoft", "DeveloperTools", "deviceid");
47+
}
48+
else
49+
{
50+
cacheFilePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".cache", "deviceid");
51+
}
52+
53+
if (File.Exists(cacheFilePath))
54+
{
55+
deviceId = File.ReadAllText(cacheFilePath);
56+
}
57+
}
58+
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
59+
{
60+
// Get device Id from macOS cache file
61+
string cacheFilePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "Library", "Application Support", "Microsoft", "DeveloperTools", "deviceid");
62+
if (File.Exists(cacheFilePath))
63+
{
64+
deviceId = File.ReadAllText(cacheFilePath);
65+
}
66+
}
67+
68+
return deviceId;
69+
}
70+
71+
private static void CacheDeviceId(string deviceId)
72+
{
73+
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
74+
{
75+
// Cache device Id in Windows registry
76+
using (var key = Registry.CurrentUser.CreateSubKey(@"SOFTWARE\Microsoft\DeveloperTools"))
77+
{
78+
key.SetValue("deviceid", deviceId);
79+
}
80+
}
81+
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
82+
{
83+
// Cache device Id in Linux cache file
84+
string cacheFilePath;
85+
string xdgCacheHome = Environment.GetEnvironmentVariable("XDG_CACHE_HOME");
86+
if (!string.IsNullOrEmpty(xdgCacheHome))
87+
{
88+
cacheFilePath = Path.Combine(xdgCacheHome, "Microsoft", "DeveloperTools", "deviceId");
89+
}
90+
else
91+
{
92+
cacheFilePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".cache", "deviceid");
93+
}
94+
95+
File.WriteAllText(cacheFilePath, deviceId);
96+
}
97+
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
98+
{
99+
// Cache device Id in macOS cache file
100+
string cacheFilePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "Library", "Application Support", "Microsoft", "DeveloperTools", "deviceid");
101+
File.WriteAllText(cacheFilePath, deviceId);
102+
}
103+
}
104+
}
105+
}

src/Cli/dotnet/Telemetry/TelemetryCommonProperties.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,15 @@ public TelemetryCommonProperties(
1414
Func<string> getCurrentDirectory = null,
1515
Func<string, string> hasher = null,
1616
Func<string> getMACAddress = null,
17+
Func<string> getDeviceId = null,
1718
IDockerContainerDetector dockerContainerDetector = null,
1819
IUserLevelCacheWriter userLevelCacheWriter = null,
1920
ICIEnvironmentDetector ciEnvironmentDetector = null)
2021
{
2122
_getCurrentDirectory = getCurrentDirectory ?? Directory.GetCurrentDirectory;
2223
_hasher = hasher ?? Sha256Hasher.Hash;
2324
_getMACAddress = getMACAddress ?? MacAddressGetter.GetMacAddress;
25+
_getDeviceId = getDeviceId ?? DeviceIdGetter.GetDeviceId;
2426
_dockerContainerDetector = dockerContainerDetector ?? new DockerContainerDetectorForTelemetry();
2527
_userLevelCacheWriter = userLevelCacheWriter ?? new UserLevelCacheWriter();
2628
_ciEnvironmentDetector = ciEnvironmentDetector ?? new CIEnvironmentDetectorForTelemetry();
@@ -31,6 +33,7 @@ public TelemetryCommonProperties(
3133
private Func<string> _getCurrentDirectory;
3234
private Func<string, string> _hasher;
3335
private Func<string> _getMACAddress;
36+
private Func<string> _getDeviceId;
3437
private IUserLevelCacheWriter _userLevelCacheWriter;
3538
private const string OSVersion = "OS Version";
3639
private const string OSPlatform = "OS Platform";
@@ -40,6 +43,7 @@ public TelemetryCommonProperties(
4043
private const string ProductVersion = "Product Version";
4144
private const string TelemetryProfile = "Telemetry Profile";
4245
private const string CurrentPathHash = "Current Path Hash";
46+
private const string DeviceId = "DeviceId";
4347
private const string MachineId = "Machine ID";
4448
private const string MachineIdOld = "Machine ID Old";
4549
private const string DockerContainer = "Docker Container";
@@ -81,6 +85,7 @@ public Dictionary<string, string> GetTelemetryCommonProperties()
8185
CliFolderPathCalculator.DotnetUserProfileFolderPath,
8286
$"{MachineIdCacheKey}.v1.dotnetUserLevelCache"),
8387
GetMachineId)},
88+
{DeviceId, _getDeviceId()},
8489
{KernelVersion, GetKernelVersion()},
8590
{InstallationType, ExternalTelemetryProperties.GetInstallationType()},
8691
{ProductType, ExternalTelemetryProperties.GetProductType()},

src/Tests/dotnet.Tests/TelemetryCommonPropertiesTests.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,13 @@ public void TelemetryCommonPropertiesShouldReturnHashedMachineId()
3333
unitUnderTest.GetTelemetryCommonProperties()["Machine ID"].Should().NotBe("plaintext");
3434
}
3535

36+
[Fact]
37+
public void TelemetryCommonPropertiesShouldReturnDevDeviceId()
38+
{
39+
var unitUnderTest = new TelemetryCommonProperties(getDeviceId: () => "plaintext", userLevelCacheWriter: new NothingCache());
40+
unitUnderTest.GetTelemetryCommonProperties()["DevDeviceId"].Should().Be("plaintext");
41+
}
42+
3643
[Fact]
3744
public void TelemetryCommonPropertiesShouldReturnNewGuidWhenCannotGetMacAddress()
3845
{
@@ -42,6 +49,15 @@ public void TelemetryCommonPropertiesShouldReturnNewGuidWhenCannotGetMacAddress(
4249
Guid.TryParse(assignedMachineId, out var _).Should().BeTrue("it should be a guid");
4350
}
4451

52+
[Fact]
53+
public void TelemetryCommonPropertiesShouldReturnNewGuidWhenCannotDevDeviceId()
54+
{
55+
var unitUnderTest = new TelemetryCommonProperties(getDeviceId: () => null, userLevelCacheWriter: new NothingCache());
56+
var assignedMachineId = unitUnderTest.GetTelemetryCommonProperties()["DevDeviceId"];
57+
58+
Guid.TryParse(assignedMachineId, out var _).Should().BeTrue("it should be a guid");
59+
}
60+
4561
[Fact]
4662
public void TelemetryCommonPropertiesShouldReturnHashedMachineIdOld()
4763
{

0 commit comments

Comments
 (0)