diff --git a/src/Aspire.Cli/Commands/AppHostLauncher.cs b/src/Aspire.Cli/Commands/AppHostLauncher.cs
index 2eeb0a397d0..fac027e55db 100644
--- a/src/Aspire.Cli/Commands/AppHostLauncher.cs
+++ b/src/Aspire.Cli/Commands/AppHostLauncher.cs
@@ -70,6 +70,7 @@ internal static void AddLaunchOptions(Command command)
/// The output format (JSON or table).
/// Whether to run in isolated mode.
/// Whether running inside VS Code extension.
+ /// Whether the AppHost is waiting for a debugger to attach.
/// Global CLI args to forward to child process.
/// Additional unmatched args to forward.
/// Cancellation token.
@@ -79,6 +80,7 @@ public async Task LaunchDetachedAsync(
OutputFormat? format,
bool isolated,
bool isExtensionHost,
+ bool waitForDebugger,
IEnumerable globalArgs,
IEnumerable additionalArgs,
CancellationToken cancellationToken)
@@ -119,6 +121,16 @@ public async Task LaunchDetachedAsync(
logger.LogDebug("Waiting for socket with prefix: {SocketPrefix}, Hash: {Hash}", expectedSocketPrefix, expectedHash);
+ // If --wait-for-debugger is active, show a message so the user knows the AppHost
+ // is paused. In detached mode we don't have the AppHost PID (stdout is suppressed),
+ // so we show a generic message without a PID.
+ if (waitForDebugger)
+ {
+ interactionService.DisplayMessage(
+ KnownEmojis.Bug,
+ InteractionServiceStrings.WaitingForDebuggerToAttachToAppHost);
+ }
+
// Start the child process and wait for the backchannel
var launchResult = await interactionService.ShowStatusAsync(
RunCommandStrings.StartingAppHostInBackground,
diff --git a/src/Aspire.Cli/Commands/RunCommand.cs b/src/Aspire.Cli/Commands/RunCommand.cs
index e13252936f2..a8f422c9974 100644
--- a/src/Aspire.Cli/Commands/RunCommand.cs
+++ b/src/Aspire.Cli/Commands/RunCommand.cs
@@ -216,6 +216,7 @@ protected override async Task ExecuteAsync(ParseResult parseResult, Cancell
// The completion sources are the contract between RunCommand and IAppHostProject
var buildCompletionSource = new TaskCompletionSource();
var backchannelCompletionSource = new TaskCompletionSource();
+ var waitForDebugger = parseResult.GetValue(RootCommand.WaitForDebuggerOption);
context = new AppHostProjectContext
{
@@ -224,14 +225,14 @@ protected override async Task ExecuteAsync(ParseResult parseResult, Cancell
Debug = parseResult.GetValue(RootCommand.DebugOption),
NoBuild = noBuild,
NoRestore = noBuild, // --no-build implies --no-restore
- WaitForDebugger = parseResult.GetValue(RootCommand.WaitForDebuggerOption),
+ WaitForDebugger = waitForDebugger,
Isolated = isolated,
StartDebugSession = startDebugSession,
EnvironmentVariables = new Dictionary(),
UnmatchedTokens = parseResult.UnmatchedTokens.ToArray(),
WorkingDirectory = ExecutionContext.WorkingDirectory,
BuildCompletionSource = buildCompletionSource,
- BackchannelCompletionSource = backchannelCompletionSource
+ BackchannelCompletionSource = backchannelCompletionSource,
};
// Start the project run as a pending task - we'll handle UX while it runs
@@ -250,6 +251,12 @@ protected override async Task ExecuteAsync(ParseResult parseResult, Cancell
return await pendingRun;
}
+ // If --wait-for-debugger, display a message so the user knows the AppHost is paused.
+ if (waitForDebugger)
+ {
+ InteractionService.DisplayMessage(KnownEmojis.Bug, InteractionServiceStrings.WaitingForDebuggerToAttachToAppHost);
+ }
+
// Now wait for the backchannel to be established
var backchannel = await InteractionService.ShowStatusAsync(
isExtensionHost ? InteractionServiceStrings.BuildingAppHost : RunCommandStrings.ConnectingToAppHost,
@@ -619,6 +626,7 @@ private Task ExecuteDetachedAsync(ParseResult parseResult, FileInfo? passed
var format = parseResult.GetValue(AppHostLauncher.s_formatOption);
var isolated = parseResult.GetValue(AppHostLauncher.s_isolatedOption);
var noBuild = parseResult.GetValue(s_noBuildOption);
+ var waitForDebugger = parseResult.GetValue(RootCommand.WaitForDebuggerOption);
var globalArgs = RootCommand.GetChildProcessArgs(parseResult);
var additionalArgs = parseResult.UnmatchedTokens.Where(t => t != "--detach").ToList();
@@ -632,6 +640,7 @@ private Task ExecuteDetachedAsync(ParseResult parseResult, FileInfo? passed
format,
isolated,
isExtensionHost,
+ waitForDebugger,
globalArgs,
additionalArgs,
cancellationToken);
diff --git a/src/Aspire.Cli/Commands/StartCommand.cs b/src/Aspire.Cli/Commands/StartCommand.cs
index 8fc1be7d9f8..2d1a301dec9 100644
--- a/src/Aspire.Cli/Commands/StartCommand.cs
+++ b/src/Aspire.Cli/Commands/StartCommand.cs
@@ -49,6 +49,7 @@ protected override async Task ExecuteAsync(ParseResult parseResult, Cancell
var noBuild = parseResult.GetValue(s_noBuildOption);
var isExtensionHost = ExtensionHelper.IsExtensionHost(_interactionService, out _, out _);
+ var waitForDebugger = parseResult.GetValue(RootCommand.WaitForDebuggerOption);
var globalArgs = RootCommand.GetChildProcessArgs(parseResult);
var additionalArgs = parseResult.UnmatchedTokens.ToList();
@@ -62,6 +63,7 @@ protected override async Task ExecuteAsync(ParseResult parseResult, Cancell
format,
isolated,
isExtensionHost,
+ waitForDebugger,
globalArgs,
additionalArgs,
cancellationToken);
diff --git a/src/Aspire.Cli/Resources/xlf/InteractionServiceStrings.cs.xlf b/src/Aspire.Cli/Resources/xlf/InteractionServiceStrings.cs.xlf
index 5f3a153d2ec..91b9765d90a 100644
--- a/src/Aspire.Cli/Resources/xlf/InteractionServiceStrings.cs.xlf
+++ b/src/Aspire.Cli/Resources/xlf/InteractionServiceStrings.cs.xlf
@@ -1,4 +1,4 @@
-
+
diff --git a/src/Aspire.Cli/Resources/xlf/InteractionServiceStrings.de.xlf b/src/Aspire.Cli/Resources/xlf/InteractionServiceStrings.de.xlf
index b5af2a6c6b2..cd413572ec8 100644
--- a/src/Aspire.Cli/Resources/xlf/InteractionServiceStrings.de.xlf
+++ b/src/Aspire.Cli/Resources/xlf/InteractionServiceStrings.de.xlf
@@ -1,4 +1,4 @@
-
+
diff --git a/src/Aspire.Cli/Resources/xlf/InteractionServiceStrings.es.xlf b/src/Aspire.Cli/Resources/xlf/InteractionServiceStrings.es.xlf
index 84a4997381a..5f2f9989b03 100644
--- a/src/Aspire.Cli/Resources/xlf/InteractionServiceStrings.es.xlf
+++ b/src/Aspire.Cli/Resources/xlf/InteractionServiceStrings.es.xlf
@@ -1,4 +1,4 @@
-
+
diff --git a/src/Aspire.Cli/Resources/xlf/InteractionServiceStrings.fr.xlf b/src/Aspire.Cli/Resources/xlf/InteractionServiceStrings.fr.xlf
index 2dc89654d20..a7497624e85 100644
--- a/src/Aspire.Cli/Resources/xlf/InteractionServiceStrings.fr.xlf
+++ b/src/Aspire.Cli/Resources/xlf/InteractionServiceStrings.fr.xlf
@@ -1,4 +1,4 @@
-
+
diff --git a/src/Aspire.Cli/Resources/xlf/InteractionServiceStrings.it.xlf b/src/Aspire.Cli/Resources/xlf/InteractionServiceStrings.it.xlf
index cc5f78af5e1..12e47f5a1f4 100644
--- a/src/Aspire.Cli/Resources/xlf/InteractionServiceStrings.it.xlf
+++ b/src/Aspire.Cli/Resources/xlf/InteractionServiceStrings.it.xlf
@@ -1,4 +1,4 @@
-
+
diff --git a/src/Aspire.Cli/Resources/xlf/InteractionServiceStrings.ja.xlf b/src/Aspire.Cli/Resources/xlf/InteractionServiceStrings.ja.xlf
index b21ac71d779..04f492987cc 100644
--- a/src/Aspire.Cli/Resources/xlf/InteractionServiceStrings.ja.xlf
+++ b/src/Aspire.Cli/Resources/xlf/InteractionServiceStrings.ja.xlf
@@ -1,4 +1,4 @@
-
+
diff --git a/src/Aspire.Cli/Resources/xlf/InteractionServiceStrings.ko.xlf b/src/Aspire.Cli/Resources/xlf/InteractionServiceStrings.ko.xlf
index f51213533f5..903d41c9fa1 100644
--- a/src/Aspire.Cli/Resources/xlf/InteractionServiceStrings.ko.xlf
+++ b/src/Aspire.Cli/Resources/xlf/InteractionServiceStrings.ko.xlf
@@ -1,4 +1,4 @@
-
+
diff --git a/src/Aspire.Cli/Resources/xlf/InteractionServiceStrings.pl.xlf b/src/Aspire.Cli/Resources/xlf/InteractionServiceStrings.pl.xlf
index 0c6650af361..dd63475344f 100644
--- a/src/Aspire.Cli/Resources/xlf/InteractionServiceStrings.pl.xlf
+++ b/src/Aspire.Cli/Resources/xlf/InteractionServiceStrings.pl.xlf
@@ -1,4 +1,4 @@
-
+
diff --git a/src/Aspire.Cli/Resources/xlf/InteractionServiceStrings.pt-BR.xlf b/src/Aspire.Cli/Resources/xlf/InteractionServiceStrings.pt-BR.xlf
index 3c3d7c3f7f0..50826012f01 100644
--- a/src/Aspire.Cli/Resources/xlf/InteractionServiceStrings.pt-BR.xlf
+++ b/src/Aspire.Cli/Resources/xlf/InteractionServiceStrings.pt-BR.xlf
@@ -1,4 +1,4 @@
-
+
diff --git a/src/Aspire.Cli/Resources/xlf/InteractionServiceStrings.ru.xlf b/src/Aspire.Cli/Resources/xlf/InteractionServiceStrings.ru.xlf
index 77f897f7e71..de044ebb0b8 100644
--- a/src/Aspire.Cli/Resources/xlf/InteractionServiceStrings.ru.xlf
+++ b/src/Aspire.Cli/Resources/xlf/InteractionServiceStrings.ru.xlf
@@ -1,4 +1,4 @@
-
+
diff --git a/src/Aspire.Cli/Resources/xlf/InteractionServiceStrings.tr.xlf b/src/Aspire.Cli/Resources/xlf/InteractionServiceStrings.tr.xlf
index 501d263bf88..db8acaa7d90 100644
--- a/src/Aspire.Cli/Resources/xlf/InteractionServiceStrings.tr.xlf
+++ b/src/Aspire.Cli/Resources/xlf/InteractionServiceStrings.tr.xlf
@@ -1,4 +1,4 @@
-
+
diff --git a/src/Aspire.Cli/Resources/xlf/InteractionServiceStrings.zh-Hans.xlf b/src/Aspire.Cli/Resources/xlf/InteractionServiceStrings.zh-Hans.xlf
index cc9ad514d33..ac2213de0e8 100644
--- a/src/Aspire.Cli/Resources/xlf/InteractionServiceStrings.zh-Hans.xlf
+++ b/src/Aspire.Cli/Resources/xlf/InteractionServiceStrings.zh-Hans.xlf
@@ -1,4 +1,4 @@
-
+
diff --git a/src/Aspire.Cli/Resources/xlf/InteractionServiceStrings.zh-Hant.xlf b/src/Aspire.Cli/Resources/xlf/InteractionServiceStrings.zh-Hant.xlf
index 32554493e18..d29c06cc2bf 100644
--- a/src/Aspire.Cli/Resources/xlf/InteractionServiceStrings.zh-Hant.xlf
+++ b/src/Aspire.Cli/Resources/xlf/InteractionServiceStrings.zh-Hant.xlf
@@ -1,4 +1,4 @@
-
+
diff --git a/src/Aspire.Hosting/DistributedApplication.cs b/src/Aspire.Hosting/DistributedApplication.cs
index af4597eb1bc..8a6f4bb559e 100644
--- a/src/Aspire.Hosting/DistributedApplication.cs
+++ b/src/Aspire.Hosting/DistributedApplication.cs
@@ -249,13 +249,15 @@ private static void WaitForDebugger()
if (Environment.GetEnvironmentVariable(KnownConfigNames.WaitForDebugger) == "true")
{
var startedWaiting = DateTimeOffset.UtcNow;
- TimeSpan timeout = TimeSpan.FromSeconds(30);
+ var timeout = TimeSpan.FromSeconds(30);
if (Environment.GetEnvironmentVariable(KnownConfigNames.WaitForDebuggerTimeout) is string timeoutString && int.TryParse(timeoutString, out var timeoutSeconds))
{
timeout = TimeSpan.FromSeconds(timeoutSeconds);
}
+ Console.WriteLine($"AppHost PID: {Environment.ProcessId}");
+
while (Debugger.IsAttached == false)
{
Console.WriteLine($"Waiting for debugger to attach to process: {Environment.ProcessId}");