.net 核心应用程序的子进程正在使用父进程的配置文件



我有2个.NET Core 2.0控制台应用程序。第一个应用程序通过system.diarostics.process.start((调用第二个应用程序。以某种方式,第二个应用程序继承了位于AppSettings.development.json中的开发配置信息。

我通过在项目的根部运行 dotnet Run 来执行第一个应用程序,或在DLL存在的文件夹中运行 dotnet firstApp.dll 。这是从PowerShell开始的。

两个应用程序都是单独的目录。我不确定这是怎么发生的。

用代码

更新

这些应用位于

C:ProjectsParentConsoleApp
C:ProjectsChildConsoleApp

这是我从父级应用程序调用应用程序的方式:

System.Diagnostics.Process.Start("dotnet", "C:\projects\ChildConsoleApp\bin\Debug\netcoreapp2.0\publish\ChildConsoleApp.dll" + $" -dt {DateTime.Now.Date.ToString("yyyy-MM-dd")}");

这就是我从JSON加载配置的方式(这两个应用程序都相同(:

class Program
{
    private static ILogger<Program> _logger;
    public static IConfigurationRoot _configuration;
    public static IServiceProvider Container { get; private set; }
    static void Main(string[] args)
    {
        RegisterServices();
        _logger = Container.GetRequiredService<ILogger<Program>>();
        _logger.LogInformation("Starting GICMON Count Scheduler Service");
        Configure();
        // At this point DBContext has value from parent! :(
        var repo = Container.GetService<ICountRepository>();
            var results = repo.Count(_configuration.GetConnectionString("DBContext"), args[0]);

    }
    private static void Configure()
    {
        string envvar = "DOTNET_ENVIRONMENT";
        string env = Environment.GetEnvironmentVariable(envvar);
        if (String.IsNullOrWhiteSpace(env))
            throw new ArgumentNullException("DOTNET_ENVIRONMENT", "Environment variable not found.");
        _logger.LogInformation($"DOTNET_ENVIRONMENT environment variable value is: {env}.");
        var builder = new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("appsettings.json");
        if (!String.IsNullOrWhiteSpace(env)) // environment == "Development"
        {
            builder.AddJsonFile($"appsettings.{env}.json", optional: true);
        }
        _configuration = builder.Build();
    }
    private static void RegisterServices()
    {
        var services = new ServiceCollection();
        services.AddSingleton<ILoggerFactory, LoggerFactory>();
        services.AddSingleton(typeof(ILogger<>), typeof(Logger<>));
        services.AddLogging((builder) => builder.SetMinimumLevel(LogLevel.Trace));
        var serviceProvider = services.BuildServiceProvider();
        var loggerFactory = serviceProvider.GetRequiredService<ILoggerFactory>();
        loggerFactory.AddNLog(new NLogProviderOptions { CaptureMessageTemplates = true, CaptureMessageProperties = true });
        loggerFactory.ConfigureNLog("nlog.config");
        Container = serviceProvider;
    }
}

问题是由于您将配置构建器设置为当前工作目录的基本路径引起的:

var builder = new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("appsettings.json");

创建子进程时,它会从父进程继承当前目录(除非您明确设置当前目录(。

因此,儿童过程基本上使用父进程目录中的JSON配置。

有几个可能的修复:

  1. 不要将基本路径设置为当前目录。

    启动应用程序时,您不确定当前目录是否匹配放置应用程序二进制文件的目录。如果您在c:testSomeApp.exe中有一个EXE文件,并在当前目录为c:时从命令行启动它,则应用程序的当前目录将为c:。在这种情况下,如果将配置构建器的基本路径设置为当前目录,则将无法加载配置文件。

    默认情况下,配置构建器从 AppContext.BaseDirectory加载配置文件,这是放置应用程序二进制文件的目录。在大多数情况下,应该是理想的行为。

    所以只需删除SetBasePath()调用:

    var builder = new ConfigurationBuilder().AddJsonFile("appsettings.json");
    
  2. 如果由于某种原因您要将配置构建器的基本路径设置为当前目录,则应为启动的子进程设置正确的当前目录:

    var childDllPath = "C:\projects\ChildConsoleApp\bin\Debug\netcoreapp2.0\publish\ChildConsoleApp.dll";
    var startInfo = new ProcessStartInfo("dotnet", childDllPath + $" -dt {DateTime.Now.Date.ToString("yyyy-MM-dd")}")
    {
        WorkingDirectory = Path.GetDirectoryName(childDllPath),
    };
    Process.Start(startInfo);
    

正如@codefuller所解释的那样,原因是两个应用程序都读取相同的appsettings.{env}.json文件。为简单起见,您可以为第二个应用程序重命名Config File(和.AddJsonFile中的相应名称(,以防止任何可能的替代。

请参阅,当您将JSON文件注册为.AddJsonFile的配置源时,配置API允许您使用所需的任何文件名,并且您没有被迫在这两个应用程序中使用相同的$"appsettings.{env}.json"模式。

最新更新