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

时间:2018-03-28 23:10:38

标签: configuration .net-core console-application

我有2个.NET Core 2.0控制台应用程序。第一个应用程序通过System.Diagnostics.Process.Start()调用第二个应用程序。不知何故,第二个应用程序继承了位于第一个应用程序的appsettings.development.json中的开发配置信息。

我通过在项目根目录中运行 dotnet run 或在DLL所在的文件夹中运行 dotnet firstapp.dll 来执行第一个应用程序。这是从Powershell开始的。

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

使用代码更新

应用程序位于

C:\Projects\ParentConsoleApp
C:\Projects\ChildConsoleApp

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

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;
    }
}

2 个答案:

答案 0 :(得分:0)

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

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

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

因此子进程基本上使用父进程目录中的JSON配置。

有几种可能的解决方法:

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

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

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

    所以只需删除var builder = new ConfigurationBuilder().AddJsonFile("appsettings.json"); 来电:

    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);
    
  2. 如果由于某种原因要将配置构建器的基本路径设置为当前目录,则应为已启动的子进程设置正确的当前目录:

    import pandas as pd
    import networkx as nx    
    import matplotlib.pyplot as plt
    
    G = nx.karate_club_graph()
    
    df = (pd.DataFrame(list(G.degree), columns=['node','degree'])
            .set_index('node'))
    df['club'] = pd.Series({node:data['club']
                            for node,data in G.nodes(data=True)})
    df['color'] = df.groupby('club')['degree'].transform(lambda c: c/c.max())
    df.loc[df['club']=='Officer', 'color'] *= -1
    
    layout = nx.fruchterman_reingold_layout(G)
    vmin = df['color'].min()
    vmax = df['color'].max()
    cmap = plt.cm.coolwarm
    
    nx.draw_networkx(G, pos=layout, with_labels=True, node_color=df['color'],
                     cmap=cmap, vmin=vmin, vmax=vmax)
    sm = plt.cm.ScalarMappable(cmap=cmap, norm=plt.Normalize(vmin=vmin, vmax=vmax))
    sm.set_array([])
    cbar = plt.colorbar(sm)
    

答案 1 :(得分:0)

正如@CodeFuller解释的那样,原因是两个应用都读取了相同的appsettings.{env}.json文件。为简单起见,您可以只为第二个应用程序重命名配置文件(以及.AddJsonFile中的相应名称)以防止任何可能的覆盖。

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