diff --git a/src/Cocona.Lite/Lite/Hosting/CoconaLiteAppHost.cs b/src/Cocona.Lite/Lite/Hosting/CoconaLiteAppHost.cs index 0770531..1a33581 100644 --- a/src/Cocona.Lite/Lite/Hosting/CoconaLiteAppHost.cs +++ b/src/Cocona.Lite/Lite/Hosting/CoconaLiteAppHost.cs @@ -1,3 +1,5 @@ +using System; +using Cocona.Application; using Cocona.Command; namespace Cocona.Lite.Hosting; @@ -21,6 +23,7 @@ public async Task RunAsync(CancellationToken cancellationToken) { var linkedCancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, _cancellationTokenSource.Token); var bootstrapper = _serviceProvider.GetRequiredService(); + var console = _serviceProvider.GetRequiredService(); #pragma warning disable RS0030 // Do not used banned APIs Console.CancelKeyPress += OnCancelKeyPress; @@ -54,6 +57,11 @@ public async Task RunAsync(CancellationToken cancellationToken) // NOTE: Ignore OperationCanceledException that was thrown by non-user code. Environment.ExitCode = 130; } + catch (Exception ex) + { + console.Error.WriteLine(ex.ToString()); + Environment.ExitCode = 1; + } _waitForShutdown.Set(); diff --git a/src/Cocona/Hosting/CoconaHostedService.cs b/src/Cocona/Hosting/CoconaHostedService.cs index 82a1a57..6e9b154 100644 --- a/src/Cocona/Hosting/CoconaHostedService.cs +++ b/src/Cocona/Hosting/CoconaHostedService.cs @@ -67,13 +67,15 @@ private async Task ExecuteCoconaApplicationAsync(Task waitForApplicationStarted) // NOTE: Ignore OperationCanceledException that was thrown by non-user code. Environment.ExitCode = 0; } - catch (Exception) + catch (Exception ex) { + _console.Error.WriteLine(ex.ToString()); Environment.ExitCode = 1; - throw; } - - _lifetime.StopApplication(); + finally + { + _lifetime.StopApplication(); + } } public async Task StopAsync(CancellationToken cancellationToken) diff --git a/test/Cocona.Test/Integration/CoconaAppRunTest.cs b/test/Cocona.Test/Integration/CoconaAppRunTest.cs index 35c7d93..1e3df85 100644 --- a/test/Cocona.Test/Integration/CoconaAppRunTest.cs +++ b/test/Cocona.Test/Integration/CoconaAppRunTest.cs @@ -989,4 +989,27 @@ class TestCommand_StopParsingOption public void A([Option]int a, [Option(StopParsingOptions = true)]string b, [Argument]string arg0, [Argument]string[] args) => Console.WriteLine($"A:{a}:{b}:{arg0}:{string.Join(",", args)}"); } + + + [Theory] + [InlineData(RunBuilderMode.CreateHostBuilder)] + [InlineData(RunBuilderMode.CreateBuilder)] + public void CoconaApp_Run_AbortOnActivationError(RunBuilderMode mode) + { + var (stdOut, stdErr, exitCode) = Run(mode, Array.Empty()); + exitCode.Should().Be(1); + stdErr.Should().StartWith("System.InvalidOperationException: Unable to resolve service"); + } + + class TestCommand_AbortOnActivationError + { + public TestCommand_AbortOnActivationError(Class1 class1) + { } + + public void A() + => Console.WriteLine($"Hello"); + + public class Class1 + { } + } }