diff --git a/src/Particular.PlatformSample/PlatformLauncher.cs b/src/Particular.PlatformSample/PlatformLauncher.cs index d06f8a4..a977b10 100644 --- a/src/Particular.PlatformSample/PlatformLauncher.cs +++ b/src/Particular.PlatformSample/PlatformLauncher.cs @@ -97,8 +97,15 @@ public static async Task Launch(bool showPlatformToolConsoleOutput = false, stri launcher.ServicePulse(pulsePort, controlPort, monitoringPort, servicePulseDefaultRoute); Console.Write("Waiting for ServiceControl to be available"); - await Network.WaitForHttpOk($"http://localhost:{controlPort}/api", stopWaiting: () => launcher.FindExitedTools().Count > 0, cancellationToken: tokenSource.Token) - .ConfigureAwait(false); + try + { + await Network.WaitForHttpOk($"http://localhost:{controlPort}/api", stopWaiting: () => launcher.FindExitedTools().Count > 0, cancellationToken: tokenSource.Token) + .ConfigureAwait(false); + } + catch (OperationCanceledException) when (tokenSource.Token.IsCancellationRequested) + { + // Ctrl+C was pressed, or the caller cancelled, before ServiceControl was available + } // A platform tool exited on its own (not because of Ctrl+C), for example because the .NET runtime version it requires is not installed var failedTools = launcher.FindExitedTools(); @@ -108,11 +115,19 @@ await Network.WaitForHttpOk($"http://localhost:{controlPort}/api", stopWaiting: { // HasExited can be true before all the error output has been read; this waits for the rest await failedTool.Process.WaitForExitAsync(CancellationToken.None).ConfigureAwait(false); - Console.WriteLine($"{failedTool.Name} failed to start:"); - Console.WriteLine(failedTool.ErrorOutput.ToString()); + Console.WriteLine($"{failedTool.Name} failed to start (exit code {failedTool.Process.ExitCode}):"); + + // Nothing is captured when the tool output is shown in the console, or when the tool exits without writing to stderr + var errorOutput = failedTool.ErrorOutput.ToString(); + Console.WriteLine(errorOutput.Length > 0 + ? errorOutput + : $"No error output was captured. Check the console output above or the logs in {Path.Combine(finder.Root, ".logs")}{Environment.NewLine}"); } launcher.StopProcesses(); + + // Launch() is usually the last call in the sample's Main, so this makes the process report the failure + Environment.ExitCode = 1; return; }