public static void SetApplicationPaths(ApplicationPaths paths, IReadOnlyCollection <string> commandLineArgs)
        {
            string?currentDomainBaseDirectory = AppDomain.CurrentDomain.BaseDirectory;

            if (WindowsServiceHelper.IsRunningAsService(commandLineArgs))
            {
                TempLogger.WriteLine(
                    $"Switching current directory from {Directory.GetCurrentDirectory()} to {currentDomainBaseDirectory}");

                Directory.SetCurrentDirectory(currentDomainBaseDirectory);
            }

            paths.BasePath ??= currentDomainBaseDirectory;
            paths.ContentBasePath ??= Directory.GetCurrentDirectory();
        }
예제 #2
0
        public static async Task <int> StartAsync(
            string[]?args,
            IReadOnlyDictionary <string, string?> environmentVariables,
            CancellationTokenSource?cancellationTokenSource = null,
            IReadOnlyCollection <Assembly>?scanAssemblies   = null,
            object[]?instances = null)
        {
            try
            {
                args ??= Array.Empty <string>();

                if (args.Length > 0)
                {
                    TempLogger.WriteLine("Started with arguments:");

                    foreach (string arg in args)
                    {
                        TempLogger.WriteLine(arg);
                    }
                }

                bool ownsCancellationToken = cancellationTokenSource is null;

                if (int.TryParse(
                        environmentVariables.GetValueOrDefault(ConfigurationConstants.RestartTimeInSeconds),
                        out int intervalInSeconds) && intervalInSeconds > 0)
                {
                    cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(intervalInSeconds));
                }

                var types = new[] { typeof(IKeyValueConfiguration) };

                foreach (var type in types)
                {
                    TempLogger.WriteLine($"Loaded type {type.FullName}");
                }

                scanAssemblies ??= ApplicationAssemblies.FilteredAssemblies(new[] { "Arbor", "Milou" });

                foreach (var scanAssembly in scanAssemblies)
                {
                    foreach (var referencedAssembly in scanAssembly.GetReferencedAssemblies())
                    {
                        try
                        {
                            AppDomain.CurrentDomain.Load(referencedAssembly);
                        }
                        catch (Exception ex)
                        {
                            TempLogger.WriteLine(ex.ToString());
                        }
                    }
                }

                cancellationTokenSource ??= new CancellationTokenSource();

                cancellationTokenSource.Token.Register(
                    () => TempLogger.WriteLine("App cancellation token triggered"));

                using App <ApplicationPipeline> app = await App <ApplicationPipeline> .CreateAsync(
                          cancellationTokenSource, args,
                          environmentVariables, scanAssemblies, instances ?? Array.Empty <object>());

                bool runAsService = app.Configuration.ValueOrDefault(ApplicationConstants.RunAsService) &&
                                    !Debugger.IsAttached;

                app.Logger.Information("Starting application {Application}", app.AppInstance);

                if (intervalInSeconds > 0)
                {
                    app.Logger.Debug(
                        "Restart time is set to {RestartIntervalInSeconds} seconds for {App}",
                        intervalInSeconds,
                        app.AppInstance);
                }
                else if (app.Logger.IsEnabled(LogEventLevel.Verbose))
                {
                    app.Logger.Verbose("Restart time is disabled");
                }

                string[] runArgs;

                if (!args.Contains(ApplicationConstants.RunAsService) && runAsService)
                {
                    runArgs = args
                              .Concat(new[] { ApplicationConstants.RunAsService })
                              .ToArray();
                }
                else
                {
                    runArgs = args;
                }

                await app.RunAsync(runArgs);

                if (!runAsService)
                {
                    app.Logger.Debug("Started {App}, waiting for web host shutdown", app.AppInstance);

                    await app.Host.WaitForShutdownAsync(cancellationTokenSource.Token);
                }

                app.Logger.Information(
                    "Stopping application {Application}",
                    app.AppInstance);

                if (ownsCancellationToken)
                {
                    cancellationTokenSource.SafeDispose();
                }

                if (int.TryParse(
                        environmentVariables.GetValueOrDefault(ConfigurationConstants.ShutdownTimeInSeconds),
                        out int shutDownTimeInSeconds) && shutDownTimeInSeconds > 0)
                {
                    await Task.Delay(TimeSpan.FromSeconds(shutDownTimeInSeconds), CancellationToken.None);
                }
            }
            catch (Exception ex)
            {
                await Task.Delay(TimeSpan.FromMilliseconds(2000));

                string?exceptionLogDirectory = args?.ParseParameter("exceptionDir");

                string logDirectory = (exceptionLogDirectory ?? AppContext.BaseDirectory);

                string fatalLogFile = Path.Combine(logDirectory, "Fatal.log");

                LoggerConfiguration loggerConfiguration = new LoggerConfiguration()
                                                          .WriteTo.File(fatalLogFile, flushToDiskInterval: TimeSpan.FromMilliseconds(50));

                if (environmentVariables.TryGetValue(LoggingConstants.SeqStartupUrl, out string?url) &&
                    Uri.TryCreate(url, UriKind.Absolute, out var uri))
                {
                    loggerConfiguration = loggerConfiguration.WriteTo.Seq(uri.AbsoluteUri);
                }

                Logger logger = loggerConfiguration
                                .MinimumLevel.Verbose()
                                .CreateLogger();

                using (logger)
                {
                    logger.Fatal(ex, "Could not start application");
                    TempLogger.FlushWith(logger);

                    await Task.Delay(TimeSpan.FromMilliseconds(1000));
                }

                string exceptionLogFile = Path.Combine(logDirectory, "Exception.log");

                await File.WriteAllTextAsync(exceptionLogFile, ex.ToString(), Encoding.UTF8);

                await Task.Delay(TimeSpan.FromMilliseconds(3000));

                return(1);
            }

            return(0);
        }
        public static async Task <int> StartAsync(string[] args,
                                                  IReadOnlyDictionary <string, string> environmentVariables,
                                                  CancellationTokenSource?cancellationTokenSource = null,
                                                  IReadOnlyCollection <Assembly>?assemblies       = null,
                                                  object[]?instances = null)
        {
            try
            {
                args ??= Array.Empty <string>();

                if (args.Length > 0)
                {
                    TempLogger.WriteLine("Started with arguments:");

                    foreach (string arg in args)
                    {
                        TempLogger.WriteLine(arg);
                    }
                }

                bool shouldDisposeCancellationToken = cancellationTokenSource is null;

                if (cancellationTokenSource is null &&
                    int.TryParse(environmentVariables.GetValueOrDefault(ConfigurationConstants.RestartTimeInSeconds),
                                 out int intervalInSeconds) &&
                    intervalInSeconds > 0)
                {
                    cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(intervalInSeconds));
                }
                else
                {
                    intervalInSeconds = 0;
                }

                cancellationTokenSource ??= new CancellationTokenSource();

                assemblies ??= ApplicationAssemblies.FilteredAssemblies();

                instances ??= Array.Empty <object>();

                try
                {
                    cancellationTokenSource.Token.Register(() =>
                                                           TempLogger.WriteLine("App cancellation token triggered"));

                    using var app = await App <T>
                                    .CreateAsync(cancellationTokenSource,
                                                 args,
                                                 environmentVariables,
                                                 assemblies,
                                                 instances).ConfigureAwait(false);

                    bool runAsService = app.Configuration.ValueOrDefault(ApplicationConstants.RunAsService) &&
                                        !Debugger.IsAttached;

                    app.Logger.Information("Starting application {Application}", app.AppInstance);

                    if (intervalInSeconds > 0)
                    {
                        app.Logger.Debug("Restart time is set to {RestartIntervalInSeconds} seconds for {App}",
                                         intervalInSeconds,
                                         app.AppInstance);
                    }
                    else if (app.Logger.IsEnabled(LogEventLevel.Verbose))
                    {
                        app.Logger.Verbose("Restart time is disabled");
                    }

                    string[] runArgs;

                    if (!args.Contains(ApplicationConstants.RunAsService) && runAsService)
                    {
                        runArgs = args.Concat(new[] { ApplicationConstants.RunAsService }).ToArray();
                    }
                    else
                    {
                        runArgs = args;
                    }

                    await app.RunAsync(runArgs).ConfigureAwait(false);

                    if (!runAsService)
                    {
                        app.Logger.Debug("Started {App}, waiting for web host shutdown", app.AppInstance);

                        await app.Host.WaitForShutdownAsync(cancellationTokenSource.Token).ConfigureAwait(false);
                    }

                    app.Logger.Information("Stopping application {Application}", app.AppInstance);
                }
                finally
                {
                    if (shouldDisposeCancellationToken)
                    {
                        cancellationTokenSource.Dispose();
                    }
                }

                if (int.TryParse(environmentVariables.GetValueOrDefault(ConfigurationConstants.ShutdownTimeInSeconds),
                                 out int shutDownTimeInSeconds) &&
                    shutDownTimeInSeconds > 0)
                {
                    await Task.Delay(TimeSpan.FromSeconds(shutDownTimeInSeconds), CancellationToken.None)
                    .ConfigureAwait(false);
                }
            }