diff --git a/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ClientConfigPaths.cs b/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ClientConfigPaths.cs index a92612ca0b0f4..224b134a8a147 100644 --- a/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ClientConfigPaths.cs +++ b/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ClientConfigPaths.cs @@ -92,7 +92,23 @@ private ClientConfigPaths(string exePath, bool includeUserConfig) } } - if (!string.IsNullOrEmpty(ApplicationUri)) + string externalConfigPath = AppDomain.CurrentDomain.GetData("APP_CONFIG_FILE") as string; + if (!string.IsNullOrEmpty(externalConfigPath)) + { + if (Uri.IsWellFormedUriString(externalConfigPath, UriKind.Absolute)) + { + Uri externalConfigUri = new Uri(externalConfigPath); + if (externalConfigUri.IsFile) + { + ApplicationConfigUri = externalConfigUri.LocalPath; + } + } + else + { + ApplicationConfigUri = Path.GetFullPath(externalConfigPath); + } + } + else if (!string.IsNullOrEmpty(ApplicationUri)) { string applicationPath = ApplicationUri; if (isSingleFile) diff --git a/src/libraries/System.Configuration.ConfigurationManager/tests/System.Configuration.ConfigurationManager.Tests.csproj b/src/libraries/System.Configuration.ConfigurationManager/tests/System.Configuration.ConfigurationManager.Tests.csproj index 94670bcb997df..816d4ca00292e 100644 --- a/src/libraries/System.Configuration.ConfigurationManager/tests/System.Configuration.ConfigurationManager.Tests.csproj +++ b/src/libraries/System.Configuration.ConfigurationManager/tests/System.Configuration.ConfigurationManager.Tests.csproj @@ -65,6 +65,7 @@ + diff --git a/src/libraries/System.Configuration.ConfigurationManager/tests/System/Configuration/ConfigurationPathTests.cs b/src/libraries/System.Configuration.ConfigurationManager/tests/System/Configuration/ConfigurationPathTests.cs new file mode 100644 index 0000000000000..5d2442dffbfe0 --- /dev/null +++ b/src/libraries/System.Configuration.ConfigurationManager/tests/System/Configuration/ConfigurationPathTests.cs @@ -0,0 +1,92 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Configuration; +using System.IO; +using Microsoft.DotNet.RemoteExecutor; +using Xunit; + +namespace System.ConfigurationTests +{ + public class ConfigurationPathTests + { + private const string ConfigName = "APP_CONFIG_FILE"; + + [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + public void CustomAppConfigIsUsedWhenSpecifiedAsRelativePath() + { + const string SettingName = "test_CustomAppConfigIsUsedWhenSpecified"; + string expectedSettingValue = Guid.NewGuid().ToString(); + string configFilePath = CreateAppConfigFileWithSetting(SettingName, expectedSettingValue); + + RemoteExecutor.Invoke((string configFilePath, string expectedSettingValue) => { + AppDomain.CurrentDomain.SetData(ConfigName, configFilePath); + Assert.Equal(expectedSettingValue, ConfigurationManager.AppSettings[SettingName]); + }, configFilePath, expectedSettingValue).Dispose(); + } + + [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + public void CustomAppConfigIsUsedWhenSpecifiedAsAbsolutePath() + { + const string SettingName = "test_CustomAppConfigIsUsedWhenSpecified"; + string expectedSettingValue = Guid.NewGuid().ToString(); + string configFilePath = Path.GetFullPath(CreateAppConfigFileWithSetting(SettingName, expectedSettingValue)); + + RemoteExecutor.Invoke((string configFilePath, string expectedSettingValue) => { + AppDomain.CurrentDomain.SetData(ConfigName, configFilePath); + Assert.Equal(expectedSettingValue, ConfigurationManager.AppSettings[SettingName]); + }, configFilePath, expectedSettingValue).Dispose(); + } + + [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + public void CustomAppConfigIsUsedWhenSpecifiedAsAbsoluteUri() + { + const string SettingName = "test_CustomAppConfigIsUsedWhenSpecified"; + string expectedSettingValue = Guid.NewGuid().ToString(); + string configFilePath = new Uri(Path.GetFullPath(CreateAppConfigFileWithSetting(SettingName, expectedSettingValue))).ToString(); + + RemoteExecutor.Invoke((string configFilePath, string expectedSettingValue) => { + AppDomain.CurrentDomain.SetData(ConfigName, configFilePath); + Assert.Equal(expectedSettingValue, ConfigurationManager.AppSettings[SettingName]); + }, configFilePath, expectedSettingValue).Dispose(); + } + + [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + public void NoErrorWhenCustomAppConfigIsSpecifiedAndItDoesNotExist() + { + RemoteExecutor.Invoke(() => + { + AppDomain.CurrentDomain.SetData(ConfigName, "non-existing-file.config"); + Assert.Null(ConfigurationManager.AppSettings["AnySetting"]); + }).Dispose(); + } + + [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + public void MalformedAppConfigCausesException() + { + const string SettingName = "AnySetting"; + + // Following will cause malformed config file + string configFilePath = CreateAppConfigFileWithSetting(SettingName, "\""); + + RemoteExecutor.Invoke((string configFilePath) => { + AppDomain.CurrentDomain.SetData(ConfigName, configFilePath); + Assert.Throws(() => ConfigurationManager.AppSettings[SettingName]); + }, configFilePath).Dispose(); + } + + private static string CreateAppConfigFileWithSetting(string key, string rawUnquotedValue) + { + string fileName = Path.GetRandomFileName() + ".config"; + File.WriteAllText(fileName, + @$" + + + + +"); + + return fileName; + } + } +}