Enforced update to file format v2.2

This commit is contained in:
Terry MacDonald 2022-01-21 20:37:56 +13:00
parent 29b592a6d1
commit f860b91a72
8 changed files with 130 additions and 99 deletions

View File

@ -291,24 +291,55 @@ namespace DisplayMagician {
//Application.SetHighDpiMode(HighDpiMode.SystemAware);
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
// Check if it's an upgrade from DisplayMagician v2.x to v2.2
// and if it is then copy the old configs to the new filenames and
// explain to the user what they need to do.
string dp22 = Path.Combine(AppProfilePath, "DisplayProfiles_2.2.json");
string dp21 = Path.Combine(AppProfilePath, "DisplayProfiles_2.1.json");
string dp20 = Path.Combine(AppProfilePath, "DisplayProfiles_2.0.json");
string dp10 = Path.Combine(AppProfilePath, "DisplayProfiles_1.0.json");
if ((File.Exists(dp21) || File.Exists(dp20)) && !File.Exists(Path.Combine(AppProfilePath, "DisplayProfiles_2.2.json")))
{
logger.Info($"Program/Main: This is an upgrade from an earlier DisplayMagician version to DisplayMagician v2.2, so performing some upgrade steps.");
// Copy the older files across to the new names, then the migrate JSON function
// within the ProfileRepository will take care of the rest
if (File.Exists(dp20))
{
File.Copy(dp20, dp22);
}
else if (File.Exists(dp21))
{
File.Copy(dp21, dp22);
}
// Warn the user about the fact we need them to recreate their Display Profiles again!
StartMessageForm myMessageWindow = new StartMessageForm();
myMessageWindow.MessageMode = "rtf";
myMessageWindow.URL = "https://displaymagician.littlebitbig.com/messages/DisplayMagician21to22.rtf";
myMessageWindow.HeadingText = "DisplayMagician v2.2 Upgrade Warning";
myMessageWindow.ButtonText = "&Close";
myMessageWindow.ShowDialog();
}
// Check if it's an upgrade from DisplayMagician v1 to v2
// and if it is then copy the old configs to the new filenames and
// explain to the user what they need to do.
// e.g. DisplayProfiles_1.0.json exists, but DisplayProfiles_2.1.json doesn't
if (File.Exists(Path.Combine(AppProfilePath, "DisplayProfiles_1.0.json")) && !File.Exists(Path.Combine(AppProfilePath, "DisplayProfiles_2.1.json")))
// e.g. DisplayProfiles_1.0.json exists, but DisplayProfiles_2.2.json doesn't
else if (File.Exists(Path.Combine(AppProfilePath, "DisplayProfiles_1.0.json")) && !File.Exists(Path.Combine(AppProfilePath, "DisplayProfiles_2.2.json")))
{
logger.Info($"Program/Main: This is an upgrade from DisplayMagician v1.0 to DisplayMagician v2.1, so performing some upgrade steps.");
logger.Info($"Program/Main: This is an upgrade from DisplayMagician v1.0 to DisplayMagician v2.2, so performing some upgrade steps.");
// Note whether we copied the old Settings file to the new v2 name earlier (before the logging was enabled)
if (upgradedSettingsFile)
{
logger.Info($"Program/Main: Upgraded v1.0 settings file {oldSettingsFile} to v2.0 settings file {newSettingsFile} earlier in loading process (before logging service was available).");
logger.Info($"Program/Main: Upgraded v1.0 settings file {oldSettingsFile} to v2.2 settings file {newSettingsFile} earlier in loading process (before logging service was available).");
}
// Copy the old Game Shortcuts file to the new v2 name
string oldShortcutsFile = Path.Combine(AppShortcutPath, "Shortcuts_1.0.json");
string newShortcutsFile = Path.Combine(AppShortcutPath, "Shortcuts_2.0.json");
string newShortcutsFile = Path.Combine(AppShortcutPath, "Shortcuts_2.2.json");
try
{
if (File.Exists(oldShortcutsFile) && !File.Exists(newShortcutsFile))
@ -325,26 +356,12 @@ namespace DisplayMagician {
// Warn the user about the fact we need a new DisplayProfiles_2.0.json
StartMessageForm myMessageWindow = new StartMessageForm();
myMessageWindow.MessageMode = "rtf";
myMessageWindow.URL = "https://displaymagician.littlebitbig.com/messages/DisplayMagician1to2.rtf";
myMessageWindow.HeadingText = "DisplayMagician v2.1.0 Upgrade Warning";
myMessageWindow.URL = "https://displaymagician.littlebitbig.com/messages/DisplayMagicianRecreateProfiles.rtf";
myMessageWindow.HeadingText = "You need to recreate your Display Profiles";
myMessageWindow.ButtonText = "&Close";
myMessageWindow.ShowDialog();
}
// Check if it's an upgrade from DisplayMagician v2.0 to v2.1
// and if it is then copy the old configs to the new filenames and
// explain to the user what they need to do.
// e.g. DisplayProfiles_2.1.json exists, but DisplayProfiles_2.0.json doesn't
else if (File.Exists(Path.Combine(AppProfilePath, "DisplayProfiles_2.0.json")) && !File.Exists(Path.Combine(AppProfilePath, "DisplayProfiles_2.1.json")))
{
logger.Info($"Program/Main: This is an upgrade from DisplayMagician v2.0 to DisplayMagician v2.1, so performing some upgrade steps.");
// Warn the user about the fact we need a new DisplayProfiles_2.0.json
StartMessageForm myMessageWindow = new StartMessageForm();
myMessageWindow.MessageMode = "rtf";
myMessageWindow.URL = "https://displaymagician.littlebitbig.com/messages/DisplayMagician20to21.rtf";
myMessageWindow.HeadingText = "DisplayMagician v2.1.0 Upgrade Warning";
myMessageWindow.ButtonText = "&Close";
myMessageWindow.ShowDialog();
}
logger.Debug($"Setting up commandline processing configuration");
var app = new CommandLineApplication

View File

@ -26,8 +26,8 @@ using System.Resources;
[assembly: Guid("e4ceaf5e-ad01-4695-b179-31168eb74c48")]
// Version information
[assembly: AssemblyVersion("2.2.0.55")]
[assembly: AssemblyFileVersion("2.2.0.55")]
[assembly: AssemblyVersion("2.2.0.72")]
[assembly: AssemblyFileVersion("2.2.0.72")]
[assembly: NeutralResourcesLanguageAttribute( "en" )]
[assembly: CLSCompliant(true)]

View File

@ -472,6 +472,20 @@ namespace DisplayMagician
_allShortcuts = JsonConvert.DeserializeObject<List<ShortcutItem>>(json, mySerializerSettings);
}
catch (JsonReaderException ex)
{
// If there is a error in the JSON format
if (ex.HResult == -2146233088)
{
MessageBox.Show($"The Game Shortcuts file {_shortcutStorageJsonFileName} contains a syntax error. Please check the file for correctness with a JSON validator.", "Error loading the Game Shortcuts", MessageBoxButtons.OK, MessageBoxIcon.Error);
SharedLogger.logger.Error(ex, $"ShortcutRepository/LoadShortcuts: JSONReaderException - The Shortcuts file {_shortcutStorageJsonFileName} contains a syntax error. Please check the file for correctness with a JSON validator.");
}
else
{
SharedLogger.logger.Error(ex, $"ShortcutRepository/LoadShortcuts: JSONReaderException while trying to process the Shortcuts json data file {_shortcutStorageJsonFileName} but JsonConvert threw an exception.");
}
}
catch (Exception ex)
{

View File

@ -540,6 +540,7 @@ namespace DisplayMagician.UIForms
Path.Combine(Program.AppLogPath,"DisplayMagician2.log"),
Path.Combine(Program.AppLogPath,"DisplayMagician3.log"),
Path.Combine(Program.AppLogPath,"DisplayMagician4.log"),
Path.Combine(Program.AppProfilePath,"DisplayProfiles_2.2.json"),
Path.Combine(Program.AppProfilePath,"DisplayProfiles_2.1.json"),
Path.Combine(Program.AppProfilePath,"DisplayProfiles_2.0.json"),
Path.Combine(Program.AppShortcutPath,"Shortcuts_2.0.json"),

View File

@ -65,7 +65,7 @@ namespace DisplayMagicianShared
public static string AppIconPath = System.IO.Path.Combine(AppDataPath, $"Icons");
public static string AppDisplayMagicianIconFilename = System.IO.Path.Combine(AppIconPath, @"DisplayMagician.ico");
private static readonly string AppProfileStoragePath = System.IO.Path.Combine(AppDataPath, $"Profiles");
private static readonly string _profileStorageJsonFileName = System.IO.Path.Combine(AppProfileStoragePath, $"DisplayProfiles_2.1.json");
private static readonly string _profileStorageJsonFileName = System.IO.Path.Combine(AppProfileStoragePath, $"DisplayProfiles_2.2.json");
@ -696,7 +696,6 @@ namespace DisplayMagicianShared
// Migrate any previous entries to the latest version of the file format to the latest one
json = MigrateJsonToLatestVersion(json);
if (!string.IsNullOrWhiteSpace(json))
{
List<string> jsonErrors = new List<string>();
@ -705,7 +704,7 @@ namespace DisplayMagicianShared
{
JsonSerializerSettings mySerializerSettings = new JsonSerializerSettings
{
MissingMemberHandling = MissingMemberHandling.Error,
MissingMemberHandling = MissingMemberHandling.Ignore,
NullValueHandling = NullValueHandling.Include,
//NullValueHandling = NullValueHandling.Ignore,
DefaultValueHandling = DefaultValueHandling.Include,
@ -721,6 +720,20 @@ namespace DisplayMagicianShared
};
_allProfiles = JsonConvert.DeserializeObject<List<ProfileItem>>(json, mySerializerSettings);
}
catch (JsonReaderException ex)
{
// If there is a error in the JSON format
if (ex.HResult == -2146233088)
{
MessageBox.Show($"The Display Profiles file {_profileStorageJsonFileName} contains a syntax error. Please check the file for correctness with a JSON validator.", "Error loading the Display Profiles", MessageBoxButtons.OK, MessageBoxIcon.Error);
SharedLogger.logger.Error(ex, $"ProfileRepository/LoadProfiles: JSONReaderException - The Display Profiles file {_profileStorageJsonFileName} contains a syntax error. Please check the file for correctness with a JSON validator.");
}
else
{
SharedLogger.logger.Error(ex, $"ProfileRepository/LoadProfiles: JSONReaderException while trying to process the Profiles json data file {_profileStorageJsonFileName} but JsonConvert threw an exception.");
}
}
catch (Exception ex)
{
@ -789,89 +802,44 @@ namespace DisplayMagicianShared
}
catch(JsonReaderException ex)
{
SharedLogger.logger.Error($"ProfileRepository/MigrateJsonToLatestVersion: JSONReaderException while trying to process the Profiles json data to migrate any older feature to the latest version.");
// If there is a error in the JSON format
if (ex.HResult == -2146233088)
{
MessageBox.Show("The Display Profiles file contains a syntax error. Please check the file for correctness with a JSON validator.", "Error loading the Display Profiles", MessageBoxButtons.OK, MessageBoxIcon.Error);
SharedLogger.logger.Error(ex, $"ProfileRepository/MigrateJsonToLatestVersion: JSONReaderException - The Display Profiles file contains a syntax error. Please check the file for correctness with a JSON validator.");
}
else
{
SharedLogger.logger.Error(ex, $"ProfileRepository/MigrateJsonToLatestVersion: JSONReaderException while trying to process the Profiles json data to migrate any older feature to the latest version.");
}
}
catch(Exception ex)
{
SharedLogger.logger.Error($"ProfileRepository/MigrateJsonToLatestVersion: Exception while trying to process the Profiles json data to migrate any older feature to the latest version.");
SharedLogger.logger.Error(ex,$"ProfileRepository/MigrateJsonToLatestVersion: Exception while trying to process the Profiles json data to migrate any older feature to the latest version.");
}
// We do the change we wre trying to do
// We do the actual change we were trying to do
try
{
/*// Now we try and add a default NVIDIA Color Settings if there isn't one
SharedLogger.logger.Trace($"ProfileRepository/MigrateJsonToLatestVersion: Looking for missing NVIDIA Color Config.");
// Create a default object
NVIDIA_DISPLAY_CONFIG myDefaultConfig = new NVIDIA_DISPLAY_CONFIG();
myDefaultConfig.ColorConfig.ColorData = new Dictionary<uint, NV_COLOR_DATA_V5>();
JObject defaultColorConfig = (JObject)JToken.FromObject(myDefaultConfig.ColorConfig);
for (int i=0; i < root.Count; i++)
{
JObject profile = (JObject)root[i];
JObject result = (JObject)profile.SelectToken("NVIDIADisplayConfig.ColorConfig.ColorData");
if (result == null)
{
JObject NVIDIADisplayConfig = (JObject)profile.SelectToken("NVIDIADisplayConfig");
NVIDIADisplayConfig.Add("ColorConfig",defaultColorConfig);
changedJson = true;
SharedLogger.logger.Trace($"ProfileRepository/MigrateJsonToLatestVersion: Patched missing NVIDIA Color Config in profile {profile.SelectToken("Name")} (index {i}).");
}
}
// Now we try to patch in a Windows GDI device context into the json if there isnt one
SharedLogger.logger.Trace($"ProfileRepository/MigrateJsonToLatestVersion: Looking for missing Windows GDI Device Context.");
// Now we try to patch in a Windows Taskbar Stuck Rects list into the json if there isnt one
SharedLogger.logger.Trace($"ProfileRepository/MigrateJsonToLatestVersion: Looking for missing Windows Taskbar settings.");
// Create a default object
Dictionary<string, GDI_DISPLAY_SETTING> GdiDisplaySettings = new Dictionary<string, GDI_DISPLAY_SETTING>();
JObject defaultGdiDisplaySettings = (JObject)JToken.FromObject(GdiDisplaySettings);
List<TaskBarStuckRectangle> taskBarStuckRectangles = new List<TaskBarStuckRectangle>();
for (int i = 0; i < root.Count; i++)
{
JObject profile = (JObject)root[i];
JObject result = (JObject)profile.SelectToken("WindowsDisplayConfig.GdiDisplaySettings");
if (result == null)
JArray WindowsTaskBarLayout = (JArray)profile.SelectToken("WindowsDisplayConfig.TaskBarLayout");
if (WindowsTaskBarLayout == null)
{
JObject WindowsDisplayConfig = (JObject)profile.SelectToken("WindowsDisplayConfig");
WindowsDisplayConfig.Add("GdiDisplaySettings", defaultGdiDisplaySettings);
JObject WindowsDisplayConfig = (JObject)profile.SelectToken("WindowsDisplayConfig");
JArray newTaskBarLayout = JArray.FromObject(taskBarStuckRectangles);
WindowsDisplayConfig.Add("TaskBarLayout",newTaskBarLayout);
changedJson = true;
SharedLogger.logger.Trace($"ProfileRepository/MigrateJsonToLatestVersion: Patched missing Windows GDI Device Context in profile {profile.SelectToken("Name")} (index {i}).");
SharedLogger.logger.Trace($"ProfileRepository/MigrateJsonToLatestVersion: Patched missing Windows TaskBarLayout in profile {profile.SelectToken("Name")} (index {i}).");
}
}
// Now we try to convert the individual sourceids into a list of source ids to cope with cloned devices
SharedLogger.logger.Trace($"ProfileRepository/MigrateJsonToLatestVersion: Looking for missing Windows GDI Device Context.");
// Create a default object
List<uint> WinDisplaySourcesList = new List<uint>();
//JObject WinDisplaySources = (JObject)JToken.FromObject(WinDisplaySourcesList);
for (int i = 0; i < root.Count; i++)
{
JObject profile = (JObject)root[i];
try
{
JObject WindowsDisplaySources = (JObject)profile.SelectToken("WindowsDisplayConfig.DisplaySources");
Dictionary<string, List<uint>> existingDisplaySources = WindowsDisplaySources.ToObject<Dictionary<string, List<uint>>>();
}
catch (Exception ex)
{
JObject WindowsDisplaySources = (JObject)profile.SelectToken("WindowsDisplayConfig.DisplaySources");
//foreach (var displaySource in WindowsDisplaySources.ToObject<Dictionary<string,uint>>())
Dictionary<string, uint> existingDisplaySources = WindowsDisplaySources.ToObject<Dictionary<string, uint>>();
Dictionary<string, List<uint>> newDisplaySources = new Dictionary<string, List<uint>>();
foreach (var sourceName in existingDisplaySources.Keys)
{
List<uint> newList = new List<uint>();
newList.Add((uint)existingDisplaySources[sourceName]);
newDisplaySources[sourceName] = newList;
}
JObject newSourcesDict = JObject.FromObject(newDisplaySources);
JToken WindowsDisplayConfig = (JToken)profile.SelectToken("WindowsDisplayConfig.DisplaySources");
WindowsDisplayConfig.Replace(newSourcesDict);
changedJson = true;
SharedLogger.logger.Trace($"ProfileRepository/MigrateJsonToLatestVersion: Patched missing Windows GDI Device Context in profile {profile.SelectToken("Name")} (index {i}).");
}
} */
}
}
catch (JsonReaderException ex)

View File

@ -16,6 +16,19 @@ namespace DisplayMagicianShared
public TaskBarStuckRectangle SingleMonitorStuckRectangle { get; set; }
public override bool Equals(object obj) => obj is TaskBarSettings other && this.Equals(other);
public bool Equals(TaskBarSettings other)
=> Options == other.Options &&
SingleMonitorStuckRectangle.Equals(other.SingleMonitorStuckRectangle);
public override int GetHashCode()
{
return (Options, SingleMonitorStuckRectangle).GetHashCode();
}
public static bool operator ==(TaskBarSettings lhs, TaskBarSettings rhs) => lhs.Equals(rhs);
public static bool operator !=(TaskBarSettings lhs, TaskBarSettings rhs) => !(lhs == rhs);
public static TaskBarSettings GetCurrent()
{
var taskBarOptions = new List<Tuple<string, int>>();

View File

@ -252,6 +252,22 @@ namespace DisplayMagicianShared
public int Version { get; set; }
public override bool Equals(object obj) => obj is TaskBarStuckRectangle other && this.Equals(other);
public bool Equals(TaskBarStuckRectangle other)
=> Version == other.Version &&
DevicePath == other.DevicePath &&
Binary.Equals(other.Binary);
public override int GetHashCode()
{
//return (DisplayConfigPaths, DisplayConfigModes, DisplayHDRStates, GdiDisplaySettings.Values, IsCloned, DisplayIdentifiers).GetHashCode();
return (Version, DevicePath, Binary).GetHashCode();
}
public static bool operator ==(TaskBarStuckRectangle lhs, TaskBarStuckRectangle rhs) => lhs.Equals(rhs);
public static bool operator !=(TaskBarStuckRectangle lhs, TaskBarStuckRectangle rhs) => !(lhs == rhs);
public static TaskBarStuckRectangle GetCurrent()
{
return GetCurrent((string)null);

View File

@ -58,7 +58,8 @@ namespace DisplayMagicianShared.Windows
// Additionally, we had to disable the DEviceKey from the equality testing within the GDI library itself as that waould also change after changing back from NVIDIA surround
// This still allows us to detect when refresh rates change, which will allow DisplayMagician to detect profile differences.
GdiDisplaySettings.Values.SequenceEqual(other.GdiDisplaySettings.Values) &&
DisplayIdentifiers.SequenceEqual(other.DisplayIdentifiers);
DisplayIdentifiers.SequenceEqual(other.DisplayIdentifiers) &&
TaskBarLayout.SequenceEqual(other.TaskBarLayout);
public override int GetHashCode()
{
@ -163,9 +164,10 @@ namespace DisplayMagicianShared.Windows
myDefaultConfig.DisplayConfigPaths = new DISPLAYCONFIG_PATH_INFO[0];
myDefaultConfig.DisplayHDRStates = new List<ADVANCED_HDR_INFO_PER_PATH>();
myDefaultConfig.DisplayIdentifiers = new List<string>();
myDefaultConfig.DisplaySources = new Dictionary<string, List<uint>>();
myDefaultConfig.IsCloned = false;
myDefaultConfig.DisplaySources = new Dictionary<string, List<uint>>();
myDefaultConfig.GdiDisplaySettings = new Dictionary<string, GDI_DISPLAY_SETTING>();
myDefaultConfig.TaskBarLayout = new List<TaskBarStuckRectangle>();
myDefaultConfig.IsCloned = false;
return myDefaultConfig;
}