Skip to content
Open
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
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## Version 1.7R (6/22/2025)

Changes in this release:

* NEW: Add support for references in settings

## Version 1.7 (7/8/2020)

Changes in this release:
Expand Down
12 changes: 12 additions & 0 deletions MODLICENSE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Modifications in This Fork

This fork of [tfabraham/EnvironmentSettingsManager](https://github.com/tfabraham/EnvironmentSettingsManager) includes changes made by @PJVervoorn.

All changes authored by @PJVervoorn are released under the [CC0 1.0 Universal](https://creativecommons.org/publicdomain/zero/1.0/) license.

These contributions are dedicated to the public domain and may be used freely, for any purpose, without attribution or restriction.

The original repository is licensed under the MIT License, which remains in effect for all unmodified portions of the code.

Original project: https://github.com/tfabraham/EnvironmentSettingsManager
Original license: [MIT License](LICENSE)
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,17 @@ The Environment Settings Manager consists of an Excel spreadsheet and an associa

The Environment Settings Manager is also integrated into the [Deployment Framework for BizTalk](https://github.com/BTDF).

## Modifications
The modifications to the Environment Settings Manager enable settings to reference other settings.
These references are in the well known format ${SettingName} and a setting can contain 0, one or more references, e.g. ${DefaultDataDrive}Archive\${ProductCode}\
Settings do not need to be in a specific order, the modifications will resolve the references in a loop (if necessary).

### See [MODLICENSE.md](MODLICENSE.md) for license notes for this fork.

## License

Copyright (c) Thomas F. Abraham. All rights reserved.

Licensed under the [MIT](LICENSE.txt) License.

Modifications authored by @PJVervoorn are released under the [CC0 1.0 Universal](https://creativecommons.org/publicdomain/zero/1.0/) license.
13 changes: 13 additions & 0 deletions src/Exporter/Constants.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace EnvironmentSettingsExporter
{
internal class Constants
{
internal const int SETTINGSNAMECOLUMN = 0;
internal const int DEFAULTVALUECOLUMN = 1;

internal const int ENVIRONMENTNAMEROW = 1;
internal const int GENERATEFILEROW = 2;
internal const int FILENAMEROW = 3;
internal const int FIRSTVALUEROW = 6;
}
}
2 changes: 2 additions & 0 deletions src/Exporter/EnvironmentSettingsExporter.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,13 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Constants.cs" />
<Compile Include="DataTableToWixCustomTableXmlExporter.cs" />
<Compile Include="DataTableToXmlPreprocessXmlExporter.cs" />
<Compile Include="DataTableToXmlExporter.cs" />
<Compile Include="DataTableToAppSettingsXmlExporter.cs" />
<Compile Include="ExcelBinarySettingsFileReader.cs" />
<Compile Include="InternalExtensions\DataTableExtensions.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="SettingsFileReader.cs" />
Expand Down
125 changes: 125 additions & 0 deletions src/Exporter/InternalExtensions/DataTableExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text.RegularExpressions;

namespace EnvironmentSettingsExporter.InternalExtensions
{
internal static class DataTableExtensions
{
private const string refPattern = @"\$\{([^}]+)\}";

internal static bool TryGetCellValue(this DataTable settingsTable, int rowIndex, int columnIndex, out string val)
{ return !string.IsNullOrEmpty((val = settingsTable.GetCellValue(rowIndex, columnIndex))); }

internal static void ResolveReferences(this DataTable settingsTable)
{
var prevColour = Console.ForegroundColor;
try
{
Console.ForegroundColor = ConsoleColor.DarkGray;
var refRegex = new Regex(refPattern);
// Start with the first column past default values
for (int columnIndex = Constants.DEFAULTVALUECOLUMN + 1;
columnIndex < settingsTable.Columns.Count && !settingsTable.Rows[Constants.FILENAMEROW].IsNull(columnIndex);
columnIndex++)
{
if (!settingsTable.TryGetCellValue(Constants.GENERATEFILEROW, columnIndex, out var val)
|| "yes".Equals(val, System.StringComparison.InvariantCultureIgnoreCase)
|| "true".Equals(val, System.StringComparison.InvariantCultureIgnoreCase))
{
Console.WriteLine($"Resolving references in '{settingsTable.GetCellValue(Constants.ENVIRONMENTNAMEROW, columnIndex)}'");

var resolvedItems = new List<Tuple<string, int, string>>();
var unresolvedItems = new List<Tuple<string, int, string>>();
var rowCount = settingsTable.Rows.Count;
for (var rowIndex = Constants.FIRSTVALUEROW; rowIndex < rowCount; rowIndex++)
{
var sn = settingsTable.GetCellValue(rowIndex, Constants.SETTINGSNAMECOLUMN);
if (!string.IsNullOrEmpty(sn))
{
var sv = settingsTable.GetSettingValue(rowIndex, columnIndex);
var t = new Tuple<string, int, string>(sn, rowIndex, sv);
if (refRegex.IsMatch(sv))
{ unresolvedItems.Add(t); }
else
{ resolvedItems.Add(t); }
}
}

//Resolving the references. Continue as long as there are unresolved items which we can resolve
bool didResolveSomething = true;
while (unresolvedItems.Count > 0 && didResolveSomething)
{
didResolveSomething = false;
foreach (var item in unresolvedItems)
{
var result = refRegex.Replace(item.Item3, m =>
{
if (resolvedItems.Exists(ri => ri.Item1.Equals(m.Groups[1].Value, StringComparison.InvariantCultureIgnoreCase)))
{
didResolveSomething = true;
return resolvedItems.Find(ri => ri.Item1.Equals(m.Groups[1].Value, StringComparison.InvariantCultureIgnoreCase)).Item3;
}
return m.Value;
});
if (didResolveSomething)
{
var newItem = new Tuple<string, int, string>(item.Item1, item.Item2, result);
unresolvedItems.Remove(item);
if (refRegex.IsMatch(result)) //we resolved something, but the cell requires more work.
{
Console.WriteLine($"\tPartially resolved reference(s) in '{item.Item1}'");
unresolvedItems.Add(newItem);
}
else //completely resolved!
{
Console.WriteLine($"\tResolved reference(s) in '{item.Item1}'");
resolvedItems.Add(newItem);
}
break; //Modified the collection, restart the loop
}
}
}

if (unresolvedItems.Count > 0)
{ throw new ApplicationException($"Settings file contains unresolved or circular references in: '{string.Join("', '", unresolvedItems.Select(t => t.Item1))}'"); }

//update the table
foreach (var item in resolvedItems)
{ settingsTable.Rows[item.Item2][columnIndex] = item.Item3; }
}
}
}
finally
{ Console.ForegroundColor = prevColour; }
}

#region Copied from DataTableToXmlExporter
internal static string GetCellValue(this DataTable settingsTable, int rowIndex, int columnIndex)
{
if (settingsTable.Rows[rowIndex].IsNull(columnIndex))
{
return string.Empty;
}
else
{
return ((string)settingsTable.Rows[rowIndex][columnIndex]).Trim();
}
}

internal static string GetSettingValue(this DataTable settingsTable, int rowIndex, int columnIndex)
{
string value = GetCellValue(settingsTable, rowIndex, columnIndex);

if (string.IsNullOrEmpty(value))
{
value = GetCellValue(settingsTable, rowIndex, Constants.DEFAULTVALUECOLUMN);
}

return value;
}
#endregion
}
}
16 changes: 10 additions & 6 deletions src/Exporter/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@
using System;
using System.Data;
using System.IO;
using System.Reflection;

namespace EnvironmentSettingsExporter
{
using InternalExtensions;

/// <summary>
/// This application reads the deployment environment settings from an EnvironmentSettings.xls/.xml Excel file
/// and exports them to one or more XML files.
Expand Down Expand Up @@ -37,13 +40,11 @@ static int Main(string[] args)
{
ConsoleColor defaultConsoleColor = Console.ForegroundColor;

Version assemblyVersion = System.Reflection.Assembly.GetEntryAssembly().GetName().Version;

var assemblyVersion = Assembly.GetEntryAssembly().GetCustomAttribute<AssemblyInformationalVersionAttribute>().InformationalVersion;
Console.ForegroundColor = ConsoleColor.White;
Console.WriteLine(
"Environment Settings Spreadsheet to XML Exporter "
+ assemblyVersion.Major + "." + assemblyVersion.Minor + "." + assemblyVersion.Build);
Console.WriteLine("[https://github.com/tfabraham/EnvironmentSettingsManager]");
Console.WriteLine($"Environment Settings Spreadsheet to XML Exporter {assemblyVersion} (Reference Edition)");
Console.WriteLine("[https://github.com/PJVervoorn/EnvironmentSettingsManager]");
Console.WriteLine("Forked from [https://github.com/tfabraham/EnvironmentSettingsManager]");
Console.WriteLine("Copyright (C) 2007 Thomas F. Abraham. All Rights Reserved.");
Console.WriteLine();
Console.ForegroundColor = defaultConsoleColor;
Expand Down Expand Up @@ -102,6 +103,9 @@ static int Main(string[] args)
settingsTable.Merge(SettingsFileReader.ReadSettingsFromExcelFile(inputFile2));
}

//Resolve references to settings with their values
settingsTable.ResolveReferences();

if (!Directory.Exists(outputPath))
{
Directory.CreateDirectory(outputPath);
Expand Down
1 change: 1 addition & 0 deletions src/Exporter/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,4 @@
//
[assembly: AssemblyVersion("1.7.0.0")]
[assembly: AssemblyFileVersion("1.7.0.0")]
[assembly: AssemblyInformationalVersion("1.7.0.0 R")]