Search code examples
c#processconsole-application.net-6.0appsettings

console applications called in System.Diagnostics.Process, use appsetting.json of caller app, instead of its appsettings


I have a console application (ParentApp for reference), which needs to call on different console application with System.Diagnostics.Process (ChildApp for reference), but when the called process runs, the ChildApp's appsettings.json is being ignored, and the ParentApp's appsettings.json is being used. The ChildApp is compiled and called by it's exe (not a shared project in the parent solution).

ChildApp being executed individually, runs fine, only face this issue when called by the ParentApp. I am new to dependency injections and not able to zero down on the possible reason for the issue. Below is the code for both, the ParentApp and ChildApp, with expected output.

The key issue in the output, is [17:57:20 INF] AppName: ParentApp instead of [17:57:18 INF] AppName: AppToTest01. as it is being read from appsettings.json

_config.GetValue<string>("Settings:AppName")

ParentApp Main

using Microsoft.Extensions.Configuration; 
using Microsoft.Extensions.DependencyInjection; 
using Microsoft.Extensions.Hosting; 
using Serilog;

internal class Program
{
    static void Main(string[] args)
    {
        string ApplicationName = "ParentApp";
        ConfigurationBuilder builder = new();
        Program program = new();
        BuildConfig(builder);

        Log.Logger = new LoggerConfiguration()
            .ReadFrom.Configuration(builder.Build())
            .WriteTo.Console()
            .WriteTo.File(@$"C:\Logs\log{ApplicationName}.txt", rollingInterval: RollingInterval.Day)
            .Enrich.FromLogContext()
            .CreateLogger();

        Log.Logger.Information("Application Starting and Injections being built");
        Log.Logger.Information($"Application Arguments: {string.Join("|", args)}");

        var host = Host.CreateDefaultBuilder()
            .ConfigureServices((context, services) =>
            {
                services.AddSingleton<IAppStartUp, AppStartUp>();
            })
            .UseSerilog()
            .Build();

        IAppStartUp svc = ActivatorUtilities.CreateInstance<AppStartUp>(host.Services);
        svc.Start();
    }

    static void BuildConfig(IConfigurationBuilder builder)
    {
        builder
            // Neither solve the issue
            //.SetBasePath(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location))
            //.SetBasePath(Environment.CurrentDirectory)
            //.SetBasePath(Directory.GetCurrentDirectory())
            .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
            .AddEnvironmentVariables();
    }
}

AppStartUp

using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using System.Diagnostics;

internal class AppStartUp : IAppStartUp
{
    private readonly ILogger<AppStartUp> _log;
    private readonly IConfiguration _config;

    public AppStartUp(ILogger<AppStartUp> log, IConfiguration config)
    {
        _log = log;
        _config = config;
    }

    public void Start()
    {
        _log.LogInformation("{Message}", "Main process started");
        _log.LogInformation("AppName: {AppName}", _config.GetValue<string>("Settings:AppName"));

        string[] ProgramPaths = _config.GetSection("TriggerProgramPath").Get<string[]>();
        foreach (string ProgramPath in ProgramPaths)
        {
            _log.LogInformation(ProgramPath);
            Process p = new();
            p.StartInfo.FileName = ProgramPath;
            p.StartInfo.RedirectStandardOutput = true;
            p.Start();

            p.WaitForExit();
            StreamReader sr = p.StandardOutput;
            string output = sr.ReadToEnd();
            _log.LogInformation(output);
        }

        Console.ReadLine();
    }
}

Appsettings.json

{
  "Settings": {
    "AppName": "ParentApp"
  },

  "TriggerProgramPath": [
    "C:\\Test 01\\AppToTest01.exe",
    "C:\\Test 02\\AppToTest01.exe"
  ]
}

ChildApp Main

using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Serilog;

internal class Program
{
    static void Main(string[] args)
    {
        string ApplicationName = "AppToTest01";
        ConfigurationBuilder builder = new();
        Program program = new();
        BuildConfig(builder);

        Log.Logger = new LoggerConfiguration()
            .ReadFrom.Configuration(builder.Build())
            .WriteTo.Console()
            .WriteTo.File(@$"C:\Logs\log{ApplicationName}.txt", rollingInterval: RollingInterval.Day)
            .Enrich.FromLogContext()
            .CreateLogger();

        Log.Logger.Information("Application Starting and Injections being built");
        Log.Logger.Information($"Application Arguments: {string.Join("|", args)}");

        var host = Host.CreateDefaultBuilder()
            .ConfigureServices((context, services) =>
            {
                services.AddTransient<IAppStartUp, AppStartUp>();
            })
            .UseSerilog()
            .Build();

        var svc = ActivatorUtilities.CreateInstance<AppStartUp>(host.Services);
        svc.Start();
    }

    static void BuildConfig(IConfigurationBuilder builder)
    {
        builder
            .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
            .AddEnvironmentVariables();
    }
}

AppStartUp

using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;

internal class AppStartUp : IAppStartUp
{
    private readonly ILogger<AppStartUp> _log;
    private readonly IConfiguration _config;

    public AppStartUp(ILogger<AppStartUp> log, IConfiguration config)
    {
        _log = log;
        _config = config;
    }

    public void Start()
    {

        _log.LogInformation("{Message}", "Main process started");
        _log.LogInformation("AppName: {AppName}", _config.GetValue<string>("Settings:AppName"));
    }
}

Appsetting.json

{
  "Settings": {
    "AppName": "AppToTest01"
  },

  "Serilog": {
    "MinimumLevel": {
      "Default": "Information",
      "Override": {
        "Microsoft": "Information",
        "System": "Warning"
      }
    }
  }
}

Desired/Expected output expected

[17:57:14 INF] Application Starting and Injections being built
[17:57:14 INF] Application Arguments:
[17:57:16 INF] Main process started
[17:57:16 INF] AppName: ParentApp

[17:57:16 INF] C:\Test 01\AppToTest01.exe
[17:57:18 INF] Application Starting and Injections being built
[17:57:18 INF] Application Arguments:
[17:57:18 INF] Main process started
[17:57:18 INF] AppName: AppToTest01

[17:57:18 INF] C:\Test 02\AppToTest02.exe
[17:57:20 INF] Application Starting and Injections being built
[17:57:20 INF] Application Arguments:
[17:57:20 INF] Main process started
[17:57:20 INF] AppName: AppToTest02

Result with the current problem

[17:57:14 INF] Application Starting and Injections being built
[17:57:14 INF] Application Arguments:
[17:57:16 INF] Main process started
[17:57:16 INF] AppName: ParentApp

[17:57:16 INF] C:\Test 01\AppToTest01.exe
[17:57:18 INF] Application Starting and Injections being built
[17:57:18 INF] Application Arguments:
[17:57:18 INF] Main process started
[17:57:18 INF] AppName: ParentApp

[17:57:18 INF] C:\Test 02\AppToTest02.exe
[17:57:20 INF] Application Starting and Injections being built
[17:57:20 INF] Application Arguments:
[17:57:20 INF] Main process started
[17:57:20 INF] AppName: ParentApp

Solution

  • Try setting ProcessStartInfo.WorkingDirectory:

    p.StartInfo.WorkingDirectory = Path.GetDirectoryName(ProgramPath);