From af3d3c2e4368c50a46d26e4f94c4fb8a0eb47662 Mon Sep 17 00:00:00 2001 From: "J. Ritchie Carroll" Date: Tue, 9 Jun 2026 16:49:26 -0400 Subject: [PATCH] GSF.*.UI.WPF: Update allows custom deployments to override the manager menu by simply adding a 'Menu.Custom.xml' alongside the application, without overwriting the base-installed 'Menu.xml' This allows custom override without removing/changing original 'Menu.xml' and also prevents possible Windows Installer component-ownership conflict. --- .../UI/WPF/UserControls/HomeUserControl.xaml.cs | 2 +- .../UI/WPF/UserControls/HomeUserControl.xaml.cs | 2 +- .../GSF.TimeSeries/UI/CommonFunctions.cs | 16 ++++++++++++++++ .../UI/WPF/UserControls/HomeUserControl.xaml.cs | 2 +- 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/Source/Libraries/GSF.PhasorProtocols/UI/WPF/UserControls/HomeUserControl.xaml.cs b/Source/Libraries/GSF.PhasorProtocols/UI/WPF/UserControls/HomeUserControl.xaml.cs index 925a24d7543..77055732708 100755 --- a/Source/Libraries/GSF.PhasorProtocols/UI/WPF/UserControls/HomeUserControl.xaml.cs +++ b/Source/Libraries/GSF.PhasorProtocols/UI/WPF/UserControls/HomeUserControl.xaml.cs @@ -144,7 +144,7 @@ public HomeUserControl() XmlRootAttribute xmlRootAttribute = new("MenuDataItems"); XmlSerializer serializer = new(typeof(ObservableCollection), xmlRootAttribute); - using XmlReader reader = XmlReader.Create(FilePath.GetAbsolutePath("Menu.xml")); + using XmlReader reader = XmlReader.Create(CommonFunctions.GetMenuFilePath()); m_menuDataItems = (ObservableCollection)serializer.Deserialize(reader); } diff --git a/Source/Libraries/GSF.TimeSeries/Transport/UI/WPF/UserControls/HomeUserControl.xaml.cs b/Source/Libraries/GSF.TimeSeries/Transport/UI/WPF/UserControls/HomeUserControl.xaml.cs index e75bc003e43..76ae0e4c11a 100755 --- a/Source/Libraries/GSF.TimeSeries/Transport/UI/WPF/UserControls/HomeUserControl.xaml.cs +++ b/Source/Libraries/GSF.TimeSeries/Transport/UI/WPF/UserControls/HomeUserControl.xaml.cs @@ -146,7 +146,7 @@ public HomeUserControl() XmlRootAttribute xmlRootAttribute = new("MenuDataItems"); XmlSerializer serializer = new(typeof(ObservableCollection), xmlRootAttribute); - using XmlReader reader = XmlReader.Create(FilePath.GetAbsolutePath("Menu.xml")); + using XmlReader reader = XmlReader.Create(CommonFunctions.GetMenuFilePath()); m_menuDataItems = (ObservableCollection)serializer.Deserialize(reader); } diff --git a/Source/Libraries/GSF.TimeSeries/UI/CommonFunctions.cs b/Source/Libraries/GSF.TimeSeries/UI/CommonFunctions.cs index 24bfa489b77..6e0b0c929b5 100755 --- a/Source/Libraries/GSF.TimeSeries/UI/CommonFunctions.cs +++ b/Source/Libraries/GSF.TimeSeries/UI/CommonFunctions.cs @@ -153,6 +153,22 @@ public static bool CanGoBack // Static Methods + /// + /// Gets the absolute path to the manager menu definition file, preferring a deployment-specific + /// Menu.Custom.xml when present and otherwise falling back to the default Menu.xml. + /// + /// Absolute path to Menu.Custom.xml when it exists; otherwise to Menu.xml. + /// + /// This allows custom or licensed deployments to override the manager menu by simply adding a + /// Menu.Custom.xml alongside the application, without overwriting the base-installed + /// Menu.xml (which would create a Windows Installer component-ownership conflict). + /// + public static string GetMenuFilePath() + { + string customMenuPath = FilePath.GetAbsolutePath("Menu.Custom.xml"); + return System.IO.File.Exists(customMenuPath) ? customMenuPath : FilePath.GetAbsolutePath("Menu.xml"); + } + #region [ AdoDataConnection Extension Methods ] /// diff --git a/Source/Libraries/GSF.TimeSeries/UI/WPF/UserControls/HomeUserControl.xaml.cs b/Source/Libraries/GSF.TimeSeries/UI/WPF/UserControls/HomeUserControl.xaml.cs index 5d4268b6cf7..be47c340cb7 100755 --- a/Source/Libraries/GSF.TimeSeries/UI/WPF/UserControls/HomeUserControl.xaml.cs +++ b/Source/Libraries/GSF.TimeSeries/UI/WPF/UserControls/HomeUserControl.xaml.cs @@ -54,7 +54,7 @@ public HomeUserControl() XmlRootAttribute xmlRootAttribute = new XmlRootAttribute("MenuDataItems"); XmlSerializer serializer = new XmlSerializer(typeof(ObservableCollection), xmlRootAttribute); - using (XmlReader reader = XmlReader.Create(FilePath.GetAbsolutePath("Menu.xml"))) + using (XmlReader reader = XmlReader.Create(CommonFunctions.GetMenuFilePath())) { m_menuDataItems = (ObservableCollection)serializer.Deserialize(reader); }