diff --git a/src/Assets/TestProjects/WatchAppWithLaunchSettings/Program.cs b/src/Assets/TestProjects/WatchAppWithLaunchSettings/Program.cs
new file mode 100644
index 000000000000..143f5183dfec
--- /dev/null
+++ b/src/Assets/TestProjects/WatchAppWithLaunchSettings/Program.cs
@@ -0,0 +1,2 @@
+Console.WriteLine("Started");
+Console.WriteLine($"Environment: {Environment.GetEnvironmentVariable("EnvironmentFromProfile")}");
diff --git a/src/Assets/TestProjects/WatchAppWithLaunchSettings/Properties/launchSettings.json b/src/Assets/TestProjects/WatchAppWithLaunchSettings/Properties/launchSettings.json
new file mode 100644
index 000000000000..f8b1abd49b2b
--- /dev/null
+++ b/src/Assets/TestProjects/WatchAppWithLaunchSettings/Properties/launchSettings.json
@@ -0,0 +1,10 @@
+{
+ "profiles": {
+ "app": {
+ "commandName": "Project",
+ "environmentVariables": {
+ "EnvironmentFromProfile": "Development"
+ }
+ }
+ }
+ }
diff --git a/src/Assets/TestProjects/WatchAppWithLaunchSettings/WatchAppWithLaunchSettings.csproj b/src/Assets/TestProjects/WatchAppWithLaunchSettings/WatchAppWithLaunchSettings.csproj
new file mode 100644
index 000000000000..74abf5c97664
--- /dev/null
+++ b/src/Assets/TestProjects/WatchAppWithLaunchSettings/WatchAppWithLaunchSettings.csproj
@@ -0,0 +1,10 @@
+
+
+
+ Exe
+ net6.0
+ enable
+ enable
+
+
+
diff --git a/src/BuiltInTools/dotnet-watch/HotReload/BlazorWebAssemblyDeltaApplier.cs b/src/BuiltInTools/dotnet-watch/HotReload/BlazorWebAssemblyDeltaApplier.cs
index 54aac04ef06f..c65ab9789b2e 100644
--- a/src/BuiltInTools/dotnet-watch/HotReload/BlazorWebAssemblyDeltaApplier.cs
+++ b/src/BuiltInTools/dotnet-watch/HotReload/BlazorWebAssemblyDeltaApplier.cs
@@ -10,11 +10,9 @@
using System.Linq;
using System.Net.WebSockets;
using System.Text;
-using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.ExternalAccess.Watch.Api;
-using Microsoft.Extensions.HotReload;
using Microsoft.Extensions.Tools.Internal;
namespace Microsoft.DotNet.Watcher.Tools
@@ -22,6 +20,7 @@ namespace Microsoft.DotNet.Watcher.Tools
internal class BlazorWebAssemblyDeltaApplier : IDeltaApplier
{
private static Task>? _cachedCapabilties;
+ private static readonly ImmutableArray _baselineCapabilities = ImmutableArray.Create("Baseline");
private readonly IReporter _reporter;
private int _sequenceId;
@@ -48,7 +47,7 @@ async Task> GetApplyUpdateCapabilitiesCoreAsync()
{
if (context.BrowserRefreshServer is null)
{
- return ImmutableArray.Empty;
+ return _baselineCapabilities;
}
await context.BrowserRefreshServer.WaitForClientConnectionAsync(cancellationToken);
@@ -58,14 +57,14 @@ async Task> GetApplyUpdateCapabilitiesCoreAsync()
var buffer = ArrayPool.Shared.Rent(32 * 1024);
try
{
- // We'll query the browser and ask it send capabilities. If the browser does not respond in 10s, we'll assume something is amiss and return
- // no capabilities. This should give you baseline hot reload capabilties.
+ // We'll query the browser and ask it send capabilities. If the browser does not respond in a short duration, we'll assume something is amiss and return
+ // baseline capabilities.
var response = await context.BrowserRefreshServer.ReceiveAsync(buffer, cancellationToken)
.AsTask()
- .WaitAsync(TimeSpan.FromSeconds(10), cancellationToken);
+ .WaitAsync(TimeSpan.FromSeconds(15), cancellationToken);
if (!response.HasValue || !response.Value.EndOfMessage || response.Value.MessageType != WebSocketMessageType.Text)
{
- return ImmutableArray.Empty;
+ return _baselineCapabilities;
}
var values = Encoding.UTF8.GetString(buffer.AsSpan(0, response.Value.Count));
@@ -83,7 +82,7 @@ async Task> GetApplyUpdateCapabilitiesCoreAsync()
ArrayPool.Shared.Return(buffer);
}
- return ImmutableArray.Empty;
+ return _baselineCapabilities;
}
}
diff --git a/src/BuiltInTools/dotnet-watch/Program.cs b/src/BuiltInTools/dotnet-watch/Program.cs
index a60b3de5d031..246f07e76291 100644
--- a/src/BuiltInTools/dotnet-watch/Program.cs
+++ b/src/BuiltInTools/dotnet-watch/Program.cs
@@ -278,7 +278,7 @@ private async Task MainInternalAsync(IReporter reporter, CommandLineOptions
_reporter.Output("Polling file watcher is enabled");
}
- var defaultProfile = LaunchSettingsProfile.ReadDefaultProfile(_workingDirectory, reporter) ?? new();
+ var defaultProfile = LaunchSettingsProfile.ReadDefaultProfile(processInfo.WorkingDirectory, reporter) ?? new();
var context = new DotNetWatchContext
{
diff --git a/src/Tests/dotnet-watch.Tests/DotNetWatcherTests.cs b/src/Tests/dotnet-watch.Tests/DotNetWatcherTests.cs
index fc71b74b3f3b..e1eb948f67e8 100644
--- a/src/Tests/dotnet-watch.Tests/DotNetWatcherTests.cs
+++ b/src/Tests/dotnet-watch.Tests/DotNetWatcherTests.cs
@@ -129,5 +129,44 @@ public async Task RunsWithRestoreIfCsprojChanges()
message = await app.Process.GetOutputLineStartsWithAsync(messagePrefix, TimeSpan.FromMinutes(2));
Assert.Equal(messagePrefix + " --no-restore -- wait", message.Trim());
}
+
+ [CoreMSBuildOnlyFact]
+ public async Task Run_WithHotReloadEnabled_ReadsLaunchSettings()
+ {
+ var testAsset = _testAssetsManager.CopyTestAsset("WatchAppWithLaunchSettings")
+ .WithSource()
+ .Path;
+
+ using var app = new WatchableApp(testAsset, _logger);
+
+ app.DotnetWatchArgs.Add("--verbose");
+
+ await app.StartWatcherAsync();
+
+ await app.Process.GetOutputLineAsync("Environment: Development", TimeSpan.FromSeconds(10));
+ }
+
+ [CoreMSBuildOnlyFact]
+ public async Task Run_WithHotReloadEnabled_ReadsLaunchSettings_WhenUsingProjectOption()
+ {
+ var testAsset = _testAssetsManager.CopyTestAsset("WatchAppWithLaunchSettings")
+ .WithSource()
+ .Path;
+
+ var directoryInfo = new DirectoryInfo(testAsset);
+ using var app = new WatchableApp(testAsset, _logger)
+ {
+ // Configure the working directory to be one level above the test app directory.
+ WorkingDirectory = Path.GetFullPath(directoryInfo.Parent.FullName),
+ };
+
+ app.DotnetWatchArgs.Add("--verbose");
+ app.DotnetWatchArgs.Add("--project");
+ app.DotnetWatchArgs.Add(Path.Combine(directoryInfo.Name, "WatchAppWithLaunchSettings.csproj"));
+
+ await app.StartWatcherAsync();
+
+ await app.Process.GetOutputLineAsync("Environment: Development", TimeSpan.FromSeconds(10));
+ }
}
}
diff --git a/src/Tests/dotnet-watch.Tests/Utilities/WatchableApp.cs b/src/Tests/dotnet-watch.Tests/Utilities/WatchableApp.cs
index d8a036559988..415f9b802219 100644
--- a/src/Tests/dotnet-watch.Tests/Utilities/WatchableApp.cs
+++ b/src/Tests/dotnet-watch.Tests/Utilities/WatchableApp.cs
@@ -38,6 +38,8 @@ public WatchableApp(string sourceDirectory, ITestOutputHelper logger)
public string SourceDirectory { get; }
+ public string WorkingDirectory { get; set; }
+
public Task HasRestarted()
=> HasRestarted(DefaultMessageTimeOut);
@@ -76,7 +78,7 @@ public void Start(IEnumerable arguments, [CallerMemberName] string name
var commandSpec = new DotnetCommand(_logger, args.ToArray())
{
- WorkingDirectory = SourceDirectory,
+ WorkingDirectory = WorkingDirectory ?? SourceDirectory,
};
commandSpec.WithEnvironmentVariable("DOTNET_USE_POLLING_FILE_WATCHER", "true");
commandSpec.WithEnvironmentVariable("__DOTNET_WATCH_RUNNING_AS_TEST", "true");