예제 #1
0
        /// <summary>
        /// Runs the application with specified command line arguments and environment variables, and returns the exit code.
        /// </summary>
        /// <remarks>
        /// If a <see cref="CommandException"/> or <see cref="TypinException"/> is thrown during command execution, it will be handled and routed to the console.
        /// Additionally, if the debugger is not attached (i.e. the app is running in production), all other exceptions thrown within
        /// this method will be handled and routed to the console as well.
        /// </remarks>
        public async ValueTask <int> RunAsync(IReadOnlyList <string> commandLineArguments,
                                              IReadOnlyDictionary <string, string> environmentVariables)
        {
            try
            {
                _console.ResetColor();
                _console.ForegroundColor = ConsoleColor.Gray;

                CliContext.EnvironmentVariables = environmentVariables;

                PrintStartupMessage();

                RootSchema root = new RootSchemaResolver(_configuration).Resolve();
                CliContext.RootSchema = root;

                //TODO: when in commandLineArguments is a string.Empty application crashes
                int exitCode = await ParseInput(commandLineArguments, root);

                return(exitCode);
            }
            // This may throw pre-execution resolving exceptions which are useful only to the end-user
            catch (TypinException ex)
            {
                _configuration.ExceptionHandler.HandleTypinException(CliContext, ex);

                return(ExitCodes.FromException(ex));
            }
            // To prevent the app from showing the annoying Windows troubleshooting dialog,
            // we handle all exceptions and route them to the console nicely.
            // However, we don't want to swallow unhandled exceptions when the debugger is attached,
            // because we still want the IDE to show them to the developer.
            catch (Exception ex) when(!Debugger.IsAttached)
            {
                _configuration.ExceptionHandler.HandleException(CliContext, ex);

                return(ExitCodes.FromException(ex));
            }
        }
예제 #2
0
        public async ValueTask <int> RunAsync(IEnumerable <string> commandLineArguments,
                                              IReadOnlyDictionary <string, string> environmentVariables)
        {
            try
            {
                _logger.LogInformation("Starting CLI application...");
                _console.ResetColor();

                _environmentVariablesAccessor.EnvironmentVariables = environmentVariables;

                RootSchema rootSchema = _rootSchemaAccessor.RootSchema; //Force root schema to resolve. TODO: find a solution to enable lazy root schema resolving.

                //TODO: OnStart()

                _startupMessage?.Invoke(_metadata, _console);

                int exitCode = await StartAppAsync(commandLineArguments);

                //TODO: OnStop()
                _logger.LogInformation("CLI application stopped.");

                return(exitCode);
            }
            // This may throw pre-execution resolving exceptions which are useful only to the end-user
            catch (TypinException ex)
            {
                _logger.LogDebug(ex, $"{nameof(TypinException)} occured. Trying to find exception handler.");

                IEnumerable <ICliExceptionHandler> exceptionHandlers = _serviceProvider.GetServices <ICliExceptionHandler>();
                foreach (ICliExceptionHandler handler in exceptionHandlers)
                {
                    if (handler.HandleException(ex))
                    {
                        _logger.LogDebug(ex, "Exception handled by {ExceptionHandlerType}.", handler.GetType().FullName);

                        break;
                    }
                }

                _logger.LogCritical(ex, "Unhandled Typin exception caused app to terminate.");

                _console.Error.WithForegroundColor(ConsoleColor.DarkRed, (error) => error.WriteLine($"Unhandled Typin exception caused app to terminate."));
                _console.Error.WriteLine();
                _console.Error.WriteException(ex);

                return(ExitCodes.FromException(ex));
            }
            // To prevent the app from showing the annoying Windows troubleshooting dialog,
            // we handle all exceptions and route them to the console nicely.
            // However, we don't want to swallow unhandled exceptions when the debugger is attached,
            // because we still want the IDE to show them to the developer.
            catch (Exception ex) //when (!Debugger.IsAttached)
            {
                _logger.LogCritical(ex, "Unhandled exception caused app to terminate.");

                _console.Error.WithForegroundColor(ConsoleColor.DarkRed, (error) => error.WriteLine($"Fatal error occured in {_metadata.ExecutableName}."));
                _console.Error.WriteLine();
                _console.Error.WriteException(ex);

                return(ExitCodes.FromException(ex));
            }
        }