437 lines
22 KiB
C#
437 lines
22 KiB
C#
using System;
|
|
using System.Configuration;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Windows.Forms;
|
|
using MigrateConfiguration.Resources;
|
|
using Installer.Common;
|
|
using System.IO;
|
|
using DTS.Common.Utilities;
|
|
|
|
namespace MigrateConfiguration
|
|
{
|
|
internal static class ConfigurationMigration
|
|
{
|
|
/// <summary>
|
|
/// Get the arguments from the MigrateConfiguration Installer Custom Action and migrates
|
|
/// the config values from the most-recently installed version of DataPRO (if any).
|
|
/// </summary>
|
|
/// <param name="args">
|
|
/// [TARGETDIR]
|
|
/// [ProductVersion]
|
|
/// </param>
|
|
private static void Main(string[] args)
|
|
{
|
|
var targetDir = string.Empty;
|
|
var productVersion = new Version();
|
|
var noUI = string.Empty;
|
|
string setupExeDir = string.Empty;
|
|
for (var i = 0; i < args.Length; i++)
|
|
{
|
|
switch (i)
|
|
{
|
|
case 0:
|
|
targetDir = args[i];
|
|
break;
|
|
case 1:
|
|
productVersion = new Version(args[i]);
|
|
break;
|
|
case 2:
|
|
noUI = args[i];
|
|
break;
|
|
case 3:
|
|
setupExeDir = args[i];
|
|
break;
|
|
}
|
|
}
|
|
try
|
|
{
|
|
if (!System.Diagnostics.EventLog.SourceExists("DataPROInstaller"))
|
|
{
|
|
System.Diagnostics.EventLog.CreateEventSource("DataPROInstaller", "DataPROInstallerLog");
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
var result = string.Empty;
|
|
|
|
var allResults = new StringBuilder();
|
|
//try
|
|
//{
|
|
// //Set the DownloadFolder setting to the current default which may be different than an old default
|
|
// //before calling UpdateConfigurationIfPossible below, so that we don't stomp on a migrated value
|
|
// //from the previous version which is not the old default.
|
|
// var settingToFind = StringResources.DownloadFolder;
|
|
// var valueToSet = StringResources.DataUpTwoLevels;
|
|
// if (!ModifyConfigSetting(targetDir, StringResources.ApplicationSettings, StringResources.DataPROWin7PropertiesSettings, settingToFind, valueToSet, out result))
|
|
// {
|
|
// allResults = CombineErrorResults(allResults, result);
|
|
// allResults.Append("\r\n");
|
|
// allResults.Append(string.Format(StringResources.ThisSettingNeedsModification, settingToFind, valueToSet));
|
|
// allResults.Append("\r\n");
|
|
// }
|
|
|
|
// //Set the ImportArchiveFolder setting so that it defaults to C:\DTS\DTS.Suite\ImportArchive (..\..\ImportArchive)
|
|
// settingToFind = StringResources.ImportArchiveFolder;
|
|
// valueToSet = StringResources.ImportArchiveUpTwoLevels;
|
|
// if (!ModifyConfigSetting(targetDir, StringResources.ApplicationSettings, StringResources.DataPROWin7PropertiesSettings, settingToFind, valueToSet, out result))
|
|
// {
|
|
// allResults = CombineErrorResults(allResults, result);
|
|
// allResults.Append("\r\n");
|
|
// allResults.Append(string.Format(StringResources.ThisSettingNeedsModification, settingToFind, valueToSet));
|
|
// allResults.Append("\r\n");
|
|
// }
|
|
//}
|
|
//catch (Exception ex)
|
|
//{
|
|
// allResults = CombineErrorResults(allResults, ex.Message);
|
|
// allResults.Append("\r\n");
|
|
//}
|
|
|
|
//Note that if the old DownloadFolder setting is the old default, we will not migrate it,
|
|
//but instead we will use the current default setting that we set above.
|
|
UpdateConfigurationIfPossible(targetDir, productVersion, setupExeDir, out result);
|
|
allResults.Append(result);
|
|
allResults.Append("\r\n");
|
|
|
|
//try
|
|
//{
|
|
// if (!FixRunTimeModulesPath(targetDir, StringResources.DTSPlugins, out result))
|
|
// {
|
|
// allResults = CombineErrorResults(allResults, result);
|
|
// allResults.Append("\r\n");
|
|
// allResults.Append(StringResources.DTSPluginsNeedsModification);
|
|
// allResults.Append("\r\n");
|
|
// }
|
|
//}
|
|
//catch (Exception ex)
|
|
//{
|
|
// allResults = CombineErrorResults(allResults, ex.Message);
|
|
// allResults.Append("\r\n");
|
|
//}
|
|
|
|
if (string.IsNullOrWhiteSpace(allResults.ToString())) return;
|
|
if (noUI != "TRUE")
|
|
{
|
|
MessageBox.Show(allResults.ToString(), StringResources.ConfigMigrationStatus, MessageBoxButtons.OK,
|
|
MessageBoxIcon.Information, MessageBoxDefaultButton.Button1,
|
|
MessageBoxOptions.DefaultDesktopOnly);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get the most-recent previously installed config file and migrate any changed settings to the newly-installed config file
|
|
/// </summary>
|
|
/// <param name="targetDir">The directory where the new config file resides.</param>
|
|
/// <param name="installingVersion">The version of DataPRO that was just installed.</param>
|
|
/// <param name="result">Text describing the success/failure of the config migration.</param>
|
|
public static void UpdateConfigurationIfPossible(string targetDir, Version installingVersion, string setupExeDir, out string result)
|
|
{
|
|
var log = new System.Diagnostics.EventLog();
|
|
log.Source = "MySource";
|
|
|
|
result = string.Empty;
|
|
var subKey = PreviousInstall.GetMostRecentlyInstalledSubKeyName(installingVersion, out string nextLowerVersion);
|
|
//log.WriteEntry("MostRecentlyInstalledSubKeyName = " + subKey);
|
|
if (string.IsNullOrWhiteSpace(subKey)) return;
|
|
var nextLowerPath = PreviousInstall.GetMostRecentlyInstalledPath(subKey);
|
|
var allResults = new StringBuilder();
|
|
|
|
_ = MigrateLicenseFile(nextLowerVersion, nextLowerPath, targetDir, setupExeDir, out var migrateLicenseResult);
|
|
allResults.AppendLine(migrateLicenseResult);
|
|
|
|
if (allResults.ToString() != StringResources.ConfigDidNotNeedToBeUpdated)
|
|
{
|
|
//Both user and application values were successful, and at least some user values were updated so
|
|
//be sure to return that information if no application values were updated.
|
|
result = allResults.ToString();
|
|
}
|
|
}
|
|
private static StringBuilder CombineErrorResults(StringBuilder allResults, string result)
|
|
{
|
|
if (allResults.Length > 0)
|
|
{
|
|
allResults.Append("\r\n");
|
|
}
|
|
allResults.Append(result);
|
|
|
|
return allResults;
|
|
}
|
|
/// <summary>
|
|
/// Migrates the UserSettings section of the config file
|
|
/// </summary>
|
|
/// <param name="nextLowerVersion">The DataPRO version of the old config file.</param>
|
|
/// <param name="nextLowerPath">The path to the old config file.</param>
|
|
/// <param name="targetDir">The path to the new config file.</param>
|
|
/// <param name="result">Text describing the success/failure of the config migration.</param>
|
|
/// <returns>True if migration succeeded or was not needed due to all defaults in the old config file, false if it failed.</returns>
|
|
private static bool MigrateUserSettings(string nextLowerVersion, string nextLowerPath, string targetDir, out string result)
|
|
{
|
|
return MigrateSettings(StringResources.UserSettings, nextLowerVersion, nextLowerPath, targetDir, out result);
|
|
}
|
|
|
|
/// <summary>
|
|
/// identifies if a file is a datapro license
|
|
/// </summary>
|
|
/// <param name="path"></param>
|
|
/// <returns></returns>
|
|
private static bool IsDataPROLicense(string path)
|
|
{
|
|
if (!File.Exists(path)) { return false; }
|
|
var contents = File.ReadAllText(path);
|
|
if (contents.Contains("<License>") && contents.Contains("<LicenseAttributes>"))
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
/// <summary>
|
|
/// finds any licenses in the directory or subdirectories
|
|
/// </summary>
|
|
/// <param name="path"></param>
|
|
/// <returns></returns>
|
|
private static string FindLicenseInPath(string path, int subDirectoriesToCheck)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(path)) { return null; }
|
|
if (!Directory.Exists(path)) { return null; }
|
|
var files = new DirectoryInfo(path).GetFiles("*.lic");
|
|
|
|
foreach (var file in files)
|
|
{
|
|
if (IsDataPROLicense(file.FullName)) { return file.FullName; }
|
|
}
|
|
if (0 >= subDirectoriesToCheck) { return null; }
|
|
subDirectoriesToCheck--;
|
|
var directories = new DirectoryInfo(path).GetDirectories();
|
|
foreach (var dir in directories)
|
|
{
|
|
var file = FindLicenseInPath(dir.FullName, subDirectoriesToCheck);
|
|
if (!string.IsNullOrWhiteSpace(file)) { return file; }
|
|
}
|
|
return null;
|
|
}
|
|
/// <summary>
|
|
/// copies license file from old installation to a new installation
|
|
/// </summary>
|
|
/// <param name="nextLowerVersion">next lowest version installed</param>
|
|
/// <param name="nextLowerPath">path to next lower version</param>
|
|
/// <param name="targetDir">the directory of the new install</param>
|
|
/// <param name="result">displayable string indicating results</param>
|
|
/// <returns>true if license file was copied, false otherwise</returns>
|
|
private static bool MigrateLicenseFile(string nextLowerVersion, string nextLowerPath, string targetDir, string setupExeDir, out string result)
|
|
{
|
|
try
|
|
{
|
|
var installVersionPath = FindLicenseInPath(new DirectoryInfo(setupExeDir).Parent.FullName, 2);
|
|
if (null != installVersionPath && File.Exists(installVersionPath))
|
|
{
|
|
var newPath = Path.Combine(targetDir, new FileInfo(installVersionPath).Name);
|
|
File.Copy(installVersionPath, newPath);
|
|
result = StringResources.InstallerLicenseFileFoundCopied;
|
|
return true;
|
|
}
|
|
var oldVersionPath = FindLicenseInPath(nextLowerPath, 2);
|
|
if (null != oldVersionPath && File.Exists(oldVersionPath))
|
|
{
|
|
var newPath = Path.Combine(targetDir, new FileInfo(oldVersionPath).Name);
|
|
File.Copy(oldVersionPath, newPath);
|
|
result = StringResources.OldLicenseFoundCopied;
|
|
return true;
|
|
}
|
|
|
|
result = StringResources.NoLicenseFound;
|
|
return false;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
result = $"{StringResources.FailedToCopyLicense} {ex.Message}";
|
|
return false;
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Migrates the ApplicationSettings section of the config file
|
|
/// </summary>
|
|
/// <param name="nextLowerVersion">The DataPRO version of the old config file.</param>
|
|
/// <param name="nextLowerPath">The path to the old config file.</param>
|
|
/// <param name="targetDir">The path to the new config file.</param>
|
|
/// <param name="result">Text describing the success/failure of the config migration.</param>
|
|
/// <returns>True if migration succeeded or was not needed due to all defaults in the old config file, false if it failed.</returns>
|
|
private static bool MigrateAppSettings(string nextLowerVersion, string nextLowerPath, string targetDir, out string result)
|
|
{
|
|
return MigrateSettings(StringResources.ApplicationSettings, nextLowerVersion, nextLowerPath, targetDir, out result);
|
|
}
|
|
/// <summary>
|
|
/// If the old config file contains an element in the new config file, and it is different, copy it to the new config file.
|
|
/// </summary>
|
|
/// <param name="settingsType">Either UserSettings or ApplicationSettings.</param>
|
|
/// <param name="nextLowerVersion">The DataPRO version of the old config file.</param>
|
|
/// <param name="nextLowerPath">The path to the old config file.</param>
|
|
/// <param name="targetDir">The path to the new config file.</param>
|
|
/// <param name="result">Text describing the success/failure of the config migration.</param>
|
|
/// <returns>True if migration succeeded or was not needed due to all defaults in the old config file, false if it failed.</returns>
|
|
private static bool MigrateSettings(string settingsType, string nextLowerVersion, string nextLowerPath, string targetDir, out string result)
|
|
{
|
|
var oldSettings = new SettingElementCollection();
|
|
if (!GetOldSettings(settingsType, nextLowerPath, out result, out oldSettings))
|
|
{
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
var newSettings = new SettingElementCollection();
|
|
Configuration newConfig;
|
|
if (!ConfigInitializationHelper.GetNewSettings(settingsType, targetDir, out result, out newSettings, out newConfig))
|
|
{
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
SaveMigratedSettings(nextLowerVersion, oldSettings, newSettings, newConfig, out result);
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Gets the settings from the old config file
|
|
/// </summary>
|
|
/// <param name="settingsType">Either UserSettings or ApplicationSettings.</param>
|
|
/// <param name="nextLowerPath">The path to the old config file.</param>
|
|
/// <param name="result">Text describing the success/failure of the config migration.</param>
|
|
/// <param name="oldSettings">The settings from the old config file</param>
|
|
/// <returns>True if the settings were successfully found and processed, false if not.</returns>
|
|
private static bool GetOldSettings(string settingsType, string nextLowerPath,
|
|
out string result, out SettingElementCollection oldSettings)
|
|
{
|
|
result = string.Empty;
|
|
oldSettings = null;
|
|
|
|
Configuration oldConfig;
|
|
var oldPath = string.Empty;
|
|
try
|
|
{
|
|
//Open the config file from the most-recently installed version of DataPRO - this assumes that it was installed in the default folder!!!
|
|
oldPath = nextLowerPath + StringResources.RegistryDataPROExe;
|
|
oldConfig = ConfigurationManager.OpenExeConfiguration(@oldPath);
|
|
}
|
|
catch (System.Exception ex)
|
|
{
|
|
result = string.Format(StringResources.OldSettingsCouldNotBeFound, ex.Message, oldPath);
|
|
return false;
|
|
}
|
|
|
|
oldSettings = GetConfigSettings(settingsType, oldConfig);
|
|
if (oldSettings != null) return true;
|
|
|
|
result = StringResources.OldSettingsCouldNotBeProcessed;
|
|
return false;
|
|
}
|
|
/// <summary>
|
|
/// Update the new config file if needed
|
|
/// </summary>
|
|
/// <param name="nextLowerVersion">The highest version installed that is lower than this version</param>
|
|
/// <param name="oldSettings">The settings from the old config file</param>
|
|
/// <param name="newSettings">The settings from the new config file</param>
|
|
/// <param name="newConfig">The config being modified</param>
|
|
/// <param name="result">Text describing the success/failure of the config migration.</param>
|
|
/// <returns>True if the settings were successfully found and processed, false if not.</returns>
|
|
private static void SaveMigratedSettings(string nextLowerVersion, SettingElementCollection oldSettings, SettingElementCollection newSettings,
|
|
Configuration newConfig, out string result)
|
|
{
|
|
var oldSettingsDictionary = oldSettings.Cast<SettingElement>().ToDictionary(oldSetting => oldSetting.Name, oldSetting => oldSetting.Value.ValueXml.InnerXml);
|
|
|
|
var settingsToBeMigrated = new SettingElementCollection();
|
|
foreach (System.Configuration.SettingElement newSetting in newSettings)
|
|
{
|
|
//If this setting exists in the old config, and it is different than the default that was installed, migrate the value
|
|
if (oldSettingsDictionary.ContainsKey(newSetting.Name) &&
|
|
oldSettingsDictionary[newSetting.Name] != newSetting.Value.ValueXml.InnerXml)
|
|
{
|
|
//Only change from the new default DownloadFolder setting to the old DownloadFolder setting if it's not the previous default ("..\Data")
|
|
if (newSetting.Name != StringResources.DownloadFolder || oldSettingsDictionary[StringResources.DownloadFolder] != StringResources.DataUpOneLevel)
|
|
{
|
|
//Add to the list of settings that need to be migrated
|
|
settingsToBeMigrated.Add(newSetting);
|
|
}
|
|
}
|
|
}
|
|
|
|
foreach (System.Configuration.SettingElement settingToBeMigrated in settingsToBeMigrated)
|
|
{
|
|
//Migrate the changed value(s)
|
|
newSettings.Remove(settingToBeMigrated);
|
|
settingToBeMigrated.Value.ValueXml.InnerXml = oldSettingsDictionary[settingToBeMigrated.Name];
|
|
newSettings.Add(settingToBeMigrated);
|
|
}
|
|
newConfig.Save();
|
|
result = settingsToBeMigrated.Count <= 0 ? StringResources.ConfigDidNotNeedToBeUpdated : string.Format(StringResources.ConfigWasUpdated, nextLowerVersion);
|
|
}
|
|
|
|
/// <summary>
|
|
/// This allows you to change a config setting.
|
|
/// </summary>
|
|
/// <param name="targetDir">The path to the config file</param>
|
|
/// <param name="sectionGroupToFind">For example, "applicationSettings"</param>
|
|
/// <param name="sectionToFind">For example, "DataPROWin7.Properties.Settings"</param>
|
|
/// <param name="settingToFind">For example, "DownloadFolder"</param>
|
|
/// <param name="valueToSet">For example, "..\..\Data"</param>
|
|
/// <param name="result"></param>
|
|
/// <returns></returns>
|
|
private static bool ModifyConfigSetting(string targetDir, string sectionGroupToFind, string sectionToFind, string settingToFind, string valueToSet, out string result)
|
|
{
|
|
result = string.Empty;
|
|
|
|
try
|
|
{
|
|
//Open the new config file just installed
|
|
var newPath = Path.Combine(targetDir, StringResources.RegistryDataPROExe);
|
|
var newConfig = ConfigurationManager.OpenExeConfiguration(@newPath);
|
|
|
|
var settingFound = false;
|
|
var newConfigSectionGroup = newConfig.SectionGroups[sectionGroupToFind];
|
|
if (newConfigSectionGroup != null)
|
|
{
|
|
var applicationSettingsSection = (ClientSettingsSection)newConfigSectionGroup.Sections[sectionToFind];
|
|
var element = applicationSettingsSection.Settings.Get(settingToFind);
|
|
|
|
if (null != element)
|
|
{
|
|
settingFound = true;
|
|
applicationSettingsSection.Settings.Remove(element);
|
|
element.Value.ValueXml.InnerXml = valueToSet;
|
|
applicationSettingsSection.Settings.Add(element);
|
|
newConfig.Save();
|
|
}
|
|
}
|
|
if (!settingFound)
|
|
{
|
|
result = string.Format(StringResources.SettingNotFound, settingToFind);
|
|
return false;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
result = ex.Message;
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
/// <summary>
|
|
/// Gets the settings in a section group of the config file.
|
|
/// </summary>
|
|
/// <param name="settingsType">Examples include "userSettings" and "applicationSettings"</param>
|
|
/// <param name="config">The config file to be interrogated.</param>
|
|
/// <returns>A collection of settings from the requested section of the config file.</returns>
|
|
private static SettingElementCollection GetConfigSettings(string settingsType, Configuration config)
|
|
{
|
|
var clientSettingsSection = new ClientSettingsSection();
|
|
var configurationSectionGroup = config.SectionGroups[settingsType];
|
|
if ((configurationSectionGroup != null) && (configurationSectionGroup.Sections[0] != null))
|
|
{
|
|
clientSettingsSection = configurationSectionGroup.Sections[0] as System.Configuration.ClientSettingsSection;
|
|
}
|
|
return clientSettingsSection?.Settings;
|
|
}
|
|
}
|
|
}
|