Skip to content
This repository was archived by the owner on Apr 20, 2023. It is now read-only.

Commit 191e3e3

Browse files
William Liwilliaml33
authored andcommitted
Installer Success Reporting for Windows
Issue https://github.com/dotnet/cli/issues/7091 Add internal command dotnet internal-reportinstallsuccess. Before Windows installer finishes, run this command instead of dotnet new. It will trigger the first time experience as well as sending telemetry with installer exe name. This command blocks to ensure that the webservice call completes.
1 parent 44cd1cf commit 191e3e3

File tree

8 files changed

+119
-5
lines changed

8 files changed

+119
-5
lines changed

packaging/windows/clisdk/bundle.wxs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
</MsiPackage>
3838
<MsiPackage SourceFile="$(var.CLISDKMsiSourcePath)">
3939
<MsiProperty Name="DOTNETHOME" Value="[DOTNETHOME]" />
40+
<MsiProperty Name="EXEFULLPATH" Value="[WixBundleOriginalSource]" />
4041
</MsiPackage>
4142
<?if $(var.Platform)=x86?>
4243
<PackageGroupRef Id="PG_AspNetCorePackageStore_x86"/>

packaging/windows/clisdk/dotnet.wxs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,20 @@
3030

3131
<CustomActionRef Id="WixBroadcastEnvironmentChange" />
3232

33-
<CustomAction Id="PropertyAssign" Property="QtExecDotnetnew" Value="&quot;[DOTNETHOME]\dotnet.exe&quot; new" Execute="immediate" />
34-
<CustomAction Id="QtExecDotnetnew" BinaryKey="WixCA" DllEntry="$(var.WixQuietExec)" Execute="deferred" Return="ignore" Impersonate="no"/>
33+
<CustomAction Id="PropertyAssignPrimeCacheAndTelemetry"
34+
Property="QtExecPrimeCacheAndTelemetryTarget"
35+
Value="&quot;[DOTNETHOME]\dotnet.exe&quot; internal-reportinstallsuccess &quot;[EXEFULLPATH]&quot;"
36+
Execute="immediate" />
37+
<CustomAction Id="QtExecPrimeCacheAndTelemetryTarget"
38+
BinaryKey="WixCA"
39+
DllEntry="$(var.WixQuietExec)"
40+
Execute="deferred"
41+
Return="ignore"
42+
Impersonate="no"/>
3543

3644
<InstallExecuteSequence>
37-
<Custom Action="PropertyAssign" Before="QtExecDotnetnew" />
38-
<Custom Action="QtExecDotnetnew" Before="InstallFinalize" />
45+
<Custom Action="PropertyAssignPrimeCacheAndTelemetry" Before="QtExecPrimeCacheAndTelemetryTarget" />
46+
<Custom Action="QtExecPrimeCacheAndTelemetryTarget" Before="InstallFinalize" />
3947
</InstallExecuteSequence>
4048
</Product>
4149
<Fragment>

src/dotnet/BuiltInCommandsCatalog.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,10 @@ public static class BuiltInCommandsCatalog
143143
["parse"] = new BuiltInCommandMetadata
144144
{
145145
Command = ParseCommand.Run
146+
},
147+
["internal-reportinstallsuccess"] = new BuiltInCommandMetadata
148+
{
149+
Command = InternalReportinstallsuccess.Run
146150
}
147151
};
148152
}

src/dotnet/Parser.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ private static void ConfigureCommandLineLocalizedStrings()
5454
Create.Command("msbuild", ""),
5555
Create.Command("vstest", ""),
5656
CompleteCommandParser.Complete(),
57+
InternalReportinstallsuccessCommandParser.InternalReportinstallsuccess(),
5758
CommonOptions.HelpOption(),
5859
Create.Option("--info", ""),
5960
Create.Option("-d", ""),

src/dotnet/Telemetry.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,15 @@ public void TrackEvent(string eventName, IDictionary<string, string> properties,
7676
);
7777
}
7878

79+
public void ThreadBlockingTrackEvent(string eventName, IDictionary<string, string> properties, IDictionary<string, double> measurements)
80+
{
81+
if (!Enabled)
82+
{
83+
return;
84+
}
85+
TrackEventTask(eventName, properties, measurements);
86+
}
87+
7988
private void InitializeTelemetry()
8089
{
8190
try
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Copyright (c) .NET Foundation and contributors. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
using System;
5+
using System.Linq;
6+
using System.IO;
7+
using System.Collections.Generic;
8+
using Microsoft.DotNet.Configurer;
9+
10+
namespace Microsoft.DotNet.Cli
11+
{
12+
public class InternalReportinstallsuccess
13+
{
14+
internal const string TelemetrySessionIdEnvironmentVariableName = "DOTNET_CLI_TELEMETRY_SESSIONID";
15+
16+
public static int Run(string[] args)
17+
{
18+
var telemetry = new ThreadBlockingTelemetry();
19+
ProcessInputAndSendTelemetry(args, telemetry);
20+
21+
return 0;
22+
}
23+
24+
public static void ProcessInputAndSendTelemetry(string[] args, ITelemetry telemetry)
25+
{
26+
var parser = Parser.Instance;
27+
var result = parser.ParseFrom("dotnet internal-reportinstallsuccess", args);
28+
29+
var internalReportinstallsuccess = result["dotnet"]["internal-reportinstallsuccess"];
30+
31+
var exeName = Path.GetFileName(internalReportinstallsuccess.Arguments.Single());
32+
telemetry.TrackEvent(
33+
"reportinstallsuccess",
34+
new Dictionary<string, string> { { "exeName", exeName } },
35+
new Dictionary<string, double>());
36+
}
37+
38+
internal class ThreadBlockingTelemetry : ITelemetry
39+
{
40+
private Telemetry telemetry;
41+
42+
internal ThreadBlockingTelemetry()
43+
{
44+
var sessionId =
45+
Environment.GetEnvironmentVariable(TelemetrySessionIdEnvironmentVariableName);
46+
telemetry = new Telemetry(new FirstTimeUseNoticeSentinel(new CliFallbackFolderPathCalculator()), sessionId);
47+
}
48+
public bool Enabled => telemetry.Enabled;
49+
50+
public void TrackEvent(string eventName, IDictionary<string, string> properties, IDictionary<string, double> measurements)
51+
{
52+
telemetry.ThreadBlockingTrackEvent(eventName, properties, measurements);
53+
}
54+
}
55+
}
56+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Copyright (c) .NET Foundation and contributors. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
using System.Linq;
5+
using Microsoft.DotNet.Cli.CommandLine;
6+
7+
namespace Microsoft.DotNet.Cli
8+
{
9+
internal static class InternalReportinstallsuccessCommandParser
10+
{
11+
public static Command InternalReportinstallsuccess() =>
12+
Create.Command(
13+
"internal-reportinstallsuccess", "internal only",
14+
Accept.ExactlyOneArgument());
15+
}
16+
}

test/dotnet.Tests/TelemetryCommandTest.cs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,15 @@ public class MockTelemetry : ITelemetry
1717
public bool Enabled { get; set; }
1818

1919
public string EventName { get; set; }
20+
public IDictionary<string, string> Properties { get; set; }
2021

2122
public void TrackEvent(string eventName, IDictionary<string, string> properties, IDictionary<string, double> measurements)
2223
{
2324
EventName = eventName;
25+
Properties = properties;
2426
}
2527
}
2628

27-
2829
public class TelemetryCommandTests : TestBase
2930
{
3031
[Fact]
@@ -35,5 +36,23 @@ public void TestProjectDependencyIsNotAvailableThroughDriver()
3536
Microsoft.DotNet.Cli.Program.ProcessArgs(args, mockTelemetry);
3637
Assert.Equal(mockTelemetry.EventName, args[0]);
3738
}
39+
40+
[Fact]
41+
public void InternalreportinstallsuccessCommandCollectExeNameWithEventname()
42+
{
43+
MockTelemetry mockTelemetry = new MockTelemetry();
44+
string[] args = { "c:\\mypath\\dotnet-sdk-latest-win-x64.exe" };
45+
46+
InternalReportinstallsuccess.ProcessInputAndSendTelemetry(args, mockTelemetry);
47+
48+
mockTelemetry.EventName.Should().Be("reportinstallsuccess");
49+
mockTelemetry.Properties["exeName"].Should().Be("dotnet-sdk-latest-win-x64.exe");
50+
}
51+
52+
[Fact]
53+
public void InternalreportinstallsuccessCommandIsRegistedInBuiltIn()
54+
{
55+
BuiltInCommandsCatalog.Commands.Should().ContainKey("internal-reportinstallsuccess");
56+
}
3857
}
3958
}

0 commit comments

Comments
 (0)