Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 74 additions & 0 deletions src/ServiceControl.Audit.UnitTests/PopulateAppSettingsTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
namespace ServiceControl.UnitTests;

using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using NUnit.Framework;

[TestFixture]
public class PopulateAppSettingsTests
{
[Test]
public async Task Should_populate_appSettings_from_exe_config_file()
{
const string MagicValue = "7303A0AA-1003-4DC4-823B-4E8B2A35CF57";

var config = $"""
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings>
<add key="ServiceControl.Audit/LogPath" value="{MagicValue}" />
</appSettings>
</configuration>
""";

await File.WriteAllTextAsync("ServiceControl.Audit.exe.config", config);

var fileName = "ServiceControl.Audit";
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
fileName = "ServiceControl.Audit.exe";
}

var startInfo = new ProcessStartInfo(fileName) { RedirectStandardOutput = true, UseShellExecute = false };

var p = Process.Start(startInfo);

if (p == null)
{
throw new Exception($"Failed to start {fileName}");
}

var pathIsSet = false;

var outputTask = Task.Run(async () =>
{
while (!p.StandardOutput.EndOfStream)
{
var line = await p.StandardOutput.ReadLineAsync();

Console.WriteLine(line);

if (line.Contains($"Logging to {MagicValue}"))
{
pathIsSet = true;
p.Kill(true);
}
}
});

if (!p.WaitForExit(5000))
{
p.Kill(true);
}

await outputTask;

Assert.That(pathIsSet, Is.True);
}

[TearDown]
public void TearDown() => File.Delete("ServiceControl.exe.config");
}
3 changes: 2 additions & 1 deletion src/ServiceControl.Audit/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@

try
{
ExeConfiguration.PopulateAppSettings(Assembly.GetExecutingAssembly());

var loggingSettings = new LoggingSettings(Settings.SettingsRootNamespace);
LoggingConfigurator.ConfigureLogging(loggingSettings);
logger = LoggerUtil.CreateStaticLogger(typeof(Program));
Expand All @@ -25,7 +27,6 @@
return exitCode;
}

ExeConfiguration.PopulateAppSettings(Assembly.GetExecutingAssembly());

var arguments = new HostArguments(args);

Expand Down
47 changes: 29 additions & 18 deletions src/ServiceControl.Configuration/ExeConfiguration.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
namespace ServiceControl.Configuration
{
using System;
using System.Configuration;
using System.IO;
using System.Linq;
Expand All @@ -12,27 +13,37 @@ public static class ExeConfiguration
// This code reads in the exe.config files and adds all the values into the ConfigurationManager's collections.
public static void PopulateAppSettings(Assembly assembly)
{
var location = Path.GetDirectoryName(assembly.Location);
var assemblyName = Path.GetFileNameWithoutExtension(assembly.Location);
var exeConfigPath = Path.Combine(location, $"{assemblyName}.exe.config");
var fileMap = new ExeConfigurationFileMap { ExeConfigFilename = exeConfigPath };
var configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);

foreach (var key in configuration.AppSettings.Settings.AllKeys)
try
{
ConfigurationManager.AppSettings.Set(key, configuration.AppSettings.Settings[key].Value);
var location = Path.GetDirectoryName(assembly.Location);
var assemblyName = Path.GetFileNameWithoutExtension(assembly.Location);
var exeConfigPath = Path.Combine(location, $"{assemblyName}.exe.config");
var fileMap = new ExeConfigurationFileMap
{
ExeConfigFilename = exeConfigPath
};
var configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);

foreach (var key in configuration.AppSettings.Settings.AllKeys)
{
ConfigurationManager.AppSettings.Set(key, configuration.AppSettings.Settings[key].Value);
}

// The connection strings collection has had its read only flag set, so we need to clear it before we can add items to it
UnsetCollectionReadonly(ConfigurationManager.ConnectionStrings);

foreach (var connectionStringSetting in configuration.ConnectionStrings.ConnectionStrings.Cast<ConnectionStringSettings>())
{
ConfigurationManager.ConnectionStrings.Add(connectionStringSetting);
}

// Put the collection back into its previous state after we're done adding items to it
SetCollectionReadOnly(ConfigurationManager.ConnectionStrings);
}

// The connection strings collection has had its read only flag set, so we need to clear it before we can add items to it
UnsetCollectionReadonly(ConfigurationManager.ConnectionStrings);

foreach (var connectionStringSetting in configuration.ConnectionStrings.ConnectionStrings.Cast<ConnectionStringSettings>())
catch (Exception e)
{
ConfigurationManager.ConnectionStrings.Add(connectionStringSetting);
throw new Exception("Failed to populate app settings.", e);
}

// Put the collection back into its previous state after we're done adding items to it
SetCollectionReadOnly(ConfigurationManager.ConnectionStrings);
}

static void UnsetCollectionReadonly(ConfigurationElementCollection collection)
Expand All @@ -47,4 +58,4 @@ static void UnsetCollectionReadonly(ConfigurationElementCollection collection)
[UnsafeAccessor(UnsafeAccessorKind.Method, Name = "SetReadOnly")]
static extern void SetCollectionReadOnly(ConfigurationElementCollection collection);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
namespace ServiceControl.UnitTests;

using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using NUnit.Framework;

[TestFixture]
public class PopulateAppSettingsTests
{
[Test]
public async Task Should_populate_appSettings_from_exe_config_file()
{
const string MagicValue = "7303A0AA-1003-4DC4-823B-4E8B2A35CF57";

var config = $"""
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings>
<add key="Monitoring/LogPath" value="{MagicValue}" />
</appSettings>
</configuration>
""";

await File.WriteAllTextAsync("ServiceControl.Monitoring.exe.config", config);

var fileName = "ServiceControl.Monitoring";
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
fileName = "ServiceControl.Monitoring.exe";
}

var startInfo = new ProcessStartInfo(fileName)
{
RedirectStandardOutput = true,
UseShellExecute = false
};

var p = Process.Start(startInfo);

if (p == null)
{
throw new Exception($"Failed to start {fileName}");
}

var pathIsSet = false;

var outputTask = Task.Run(async () =>
{
while (!p.StandardOutput.EndOfStream)
{
var line = await p.StandardOutput.ReadLineAsync();

Console.WriteLine(line);

if (line.Contains($"Logging to {MagicValue}"))
{
pathIsSet = true;
p.Kill(true);
}
}
});

if (!p.WaitForExit(5000))
{
p.Kill(true);
}

await outputTask;

Assert.That(pathIsSet, Is.True);
}

[TearDown]
public void TearDown() => File.Delete("ServiceControl.exe.config");
}
4 changes: 2 additions & 2 deletions src/ServiceControl.Monitoring/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

try
{
ExeConfiguration.PopulateAppSettings(Assembly.GetExecutingAssembly());

var loggingSettings = new LoggingSettings(Settings.SettingsRootNamespace);
LoggingConfigurator.ConfigureLogging(loggingSettings);
logger = LoggerUtil.CreateStaticLogger(typeof(Program));
Expand All @@ -23,8 +25,6 @@
return exitCode;
}

ExeConfiguration.PopulateAppSettings(Assembly.GetExecutingAssembly());

var arguments = new HostArguments(args);

var settings = new Settings(loggingSettings: loggingSettings);
Expand Down
76 changes: 76 additions & 0 deletions src/ServiceControl.UnitTests/PopulateAppSettingsTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
namespace ServiceControl.UnitTests;

using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using NUnit.Framework;

[TestFixture]
public class PopulateAppSettingsTests
{
[Test]
public async Task Should_populate_appSettings_from_exe_config_file()
{
const string MagicValue = "7303A0AA-1003-4DC4-823B-4E8B2A35CF57";

var config = $"""
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings>
<add key="ServiceControl/LogPath" value="{MagicValue}" />
</appSettings>
</configuration>
""";

await File.WriteAllTextAsync("ServiceControl.exe.config", config);

var fileName = "ServiceControl";
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
fileName = "ServiceControl.exe";
}

var startInfo = new ProcessStartInfo(fileName)
{
RedirectStandardOutput = true,
UseShellExecute = false
};

var p = Process.Start(startInfo);

if (p == null)
{
throw new Exception("Failed to start ServiceControl");
}

var pathIsSet = false;

var outputTask = Task.Run(async () =>
{
while (!p.StandardOutput.EndOfStream)
{
var line = await p.StandardOutput.ReadLineAsync();

if (line.Contains($"Logging to {MagicValue}"))
{
pathIsSet = true;
p.Kill(true);
}
}
});

if (!p.WaitForExit(5000))
{
p.Kill(true);
}

await outputTask;

Assert.That(pathIsSet, Is.True);
}

[TearDown]
public void TearDown() => File.Delete("ServiceControl.exe.config");
}
4 changes: 2 additions & 2 deletions src/ServiceControl/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@

try
{
ExeConfiguration.PopulateAppSettings(Assembly.GetExecutingAssembly());

var loggingSettings = new LoggingSettings(Settings.SettingsRootNamespace);
LoggingConfigurator.ConfigureLogging(loggingSettings);
logger = LoggerUtil.CreateStaticLogger(typeof(Program));
Expand All @@ -25,8 +27,6 @@
return exitCode;
}

ExeConfiguration.PopulateAppSettings(Assembly.GetExecutingAssembly());

var arguments = new HostArguments(args);

if (arguments.Help)
Expand Down