From 24ad9e15c681cc25236d7e45e06e1abf65f041f5 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 9 Feb 2026 20:08:29 +0000
Subject: [PATCH 01/25] Initial plan
From 122558723af9a278b7e7cf33f6dc6696e1802c62 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 9 Feb 2026 20:11:14 +0000
Subject: [PATCH 02/25] Add policy to override SettingsFolder Location
Co-authored-by: BornToBeRoot <16019165+BornToBeRoot@users.noreply.github.com>
---
Source/NETworkManager.Settings/PolicyInfo.cs | 3 ++
.../NETworkManager.Settings/PolicyManager.cs | 1 +
.../SettingsManager.cs | 5 ++
.../config.json.example | 3 +-
Website/docs/settings/settings.md | 4 ++
Website/docs/system-wide-policies.md | 49 ++++++++++++++++++-
6 files changed, 63 insertions(+), 2 deletions(-)
diff --git a/Source/NETworkManager.Settings/PolicyInfo.cs b/Source/NETworkManager.Settings/PolicyInfo.cs
index 7b9b64a6a0..0a7f512ba3 100644
--- a/Source/NETworkManager.Settings/PolicyInfo.cs
+++ b/Source/NETworkManager.Settings/PolicyInfo.cs
@@ -10,4 +10,7 @@ public class PolicyInfo
{
[JsonPropertyName("Update_CheckForUpdatesAtStartup")]
public bool? Update_CheckForUpdatesAtStartup { get; set; }
+
+ [JsonPropertyName("SettingsFolderLocation")]
+ public string SettingsFolderLocation { get; set; }
}
diff --git a/Source/NETworkManager.Settings/PolicyManager.cs b/Source/NETworkManager.Settings/PolicyManager.cs
index 7dd762c8de..fc946620bc 100644
--- a/Source/NETworkManager.Settings/PolicyManager.cs
+++ b/Source/NETworkManager.Settings/PolicyManager.cs
@@ -83,6 +83,7 @@ public static void Load()
// Log enabled settings
Log.Info($"System-wide policy - Update_CheckForUpdatesAtStartup: {Current.Update_CheckForUpdatesAtStartup?.ToString() ?? "Not set"}");
+ Log.Info($"System-wide policy - SettingsFolderLocation: {Current.SettingsFolderLocation ?? "Not set"}");
}
}
catch (Exception ex)
diff --git a/Source/NETworkManager.Settings/SettingsManager.cs b/Source/NETworkManager.Settings/SettingsManager.cs
index 29a140218e..83241bde51 100644
--- a/Source/NETworkManager.Settings/SettingsManager.cs
+++ b/Source/NETworkManager.Settings/SettingsManager.cs
@@ -77,6 +77,11 @@ public static class SettingsManager
/// Path to the settings folder.
public static string GetSettingsFolderLocation()
{
+ // Policy override takes precedence
+ if (!string.IsNullOrWhiteSpace(PolicyManager.Current?.SettingsFolderLocation))
+ return PolicyManager.Current.SettingsFolderLocation;
+
+ // Fall back to existing logic
return ConfigurationManager.Current.IsPortable
? Path.Combine(AssemblyManager.Current.Location, SettingsFolderName)
: Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
diff --git a/Source/NETworkManager.Settings/config.json.example b/Source/NETworkManager.Settings/config.json.example
index 8ca2bf05b3..0a47ffa700 100644
--- a/Source/NETworkManager.Settings/config.json.example
+++ b/Source/NETworkManager.Settings/config.json.example
@@ -1,3 +1,4 @@
{
- "Update_CheckForUpdatesAtStartup": false
+ "Update_CheckForUpdatesAtStartup": false,
+ "SettingsFolderLocation": "C:\\CustomPath\\NETworkManager\\Settings"
}
\ No newline at end of file
diff --git a/Website/docs/settings/settings.md b/Website/docs/settings/settings.md
index 32342b3d6e..f4404603c2 100644
--- a/Website/docs/settings/settings.md
+++ b/Website/docs/settings/settings.md
@@ -17,6 +17,10 @@ Folder where the application settings are stored.
| Setup / Archiv | `%UserProfile%\Documents\NETworkManager\Settings` |
| Portable | `\Settings` |
+**Policy Override**: `SettingsFolderLocation`
+
+This setting can be overridden by a [system-wide policy](../system-wide-policies.md). When a policy is configured, it takes precedence over the default location, allowing administrators to specify a custom settings folder path for all users.
+
:::note
**Recommendation**
diff --git a/Website/docs/system-wide-policies.md b/Website/docs/system-wide-policies.md
index d8ef644453..56e85d6b5d 100644
--- a/Website/docs/system-wide-policies.md
+++ b/Website/docs/system-wide-policies.md
@@ -36,7 +36,8 @@ The `config.json` file uses a simple JSON structure to define policy values. An
```json
{
- "Update_CheckForUpdatesAtStartup": false
+ "Update_CheckForUpdatesAtStartup": false,
+ "SettingsFolderLocation": "C:\\ProgramData\\NETworkManager\\Settings"
}
```
@@ -97,6 +98,52 @@ Ensure the `config.json` file has appropriate permissions so that regular users
- Verify the value is a boolean (`true` or `false`), not a string (`"true"` or `"false"`)
- Check that there are no syntax errors in the JSON file
+## Available Policies
+
+### Update_CheckForUpdatesAtStartup
+
+Control whether the application checks for updates at startup.
+
+**Type**: `Boolean` (true/false)
+
+**Default**: User setting applies
+
+**Example**:
+```json
+{
+ "Update_CheckForUpdatesAtStartup": false
+}
+```
+
+See [Check for updates at startup](./settings/update.md#check-for-updates-at-startup) for more details.
+
+### SettingsFolderLocation
+
+Override the default location where application settings are stored.
+
+**Type**: `String` (absolute path)
+
+**Default**: User Documents folder or portable location
+
+**Example**:
+```json
+{
+ "SettingsFolderLocation": "C:\\ProgramData\\NETworkManager\\Settings"
+}
+```
+
+See [Location](./settings/settings.md#location) for more details.
+
+:::warning
+
+When configuring a custom settings folder location, ensure:
+- The path uses double backslashes (`\\`) in JSON format
+- The application has read/write permissions to the specified directory
+- The directory exists or the application has permissions to create it
+- All users have appropriate access to the folder if using a shared location
+
+:::
+
## Future Policies
Additional policy options will be added in future releases to provide more granular control over application behavior. If you have specific requirements for system-wide policies in your organization, please submit a feature request via the [GitHub issue tracker](https://github.com/BornToBeRoot/NETworkManager/issues/new/choose).
From bf0c78e8df2ec8d14ab38a4e760ef18d194b3419 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 9 Feb 2026 20:13:00 +0000
Subject: [PATCH 03/25] Add validation for policy-provided
SettingsFolderLocation
Co-authored-by: BornToBeRoot <16019165+BornToBeRoot@users.noreply.github.com>
---
Source/NETworkManager.Settings/PolicyInfo.cs | 2 +-
.../SettingsManager.cs | 24 ++++++++++++++++++-
Website/docs/system-wide-policies.md | 4 ++++
3 files changed, 28 insertions(+), 2 deletions(-)
diff --git a/Source/NETworkManager.Settings/PolicyInfo.cs b/Source/NETworkManager.Settings/PolicyInfo.cs
index 0a7f512ba3..2f17ee8abf 100644
--- a/Source/NETworkManager.Settings/PolicyInfo.cs
+++ b/Source/NETworkManager.Settings/PolicyInfo.cs
@@ -12,5 +12,5 @@ public class PolicyInfo
public bool? Update_CheckForUpdatesAtStartup { get; set; }
[JsonPropertyName("SettingsFolderLocation")]
- public string SettingsFolderLocation { get; set; }
+ public string? SettingsFolderLocation { get; set; }
}
diff --git a/Source/NETworkManager.Settings/SettingsManager.cs b/Source/NETworkManager.Settings/SettingsManager.cs
index 83241bde51..1343bf2c81 100644
--- a/Source/NETworkManager.Settings/SettingsManager.cs
+++ b/Source/NETworkManager.Settings/SettingsManager.cs
@@ -79,7 +79,29 @@ public static string GetSettingsFolderLocation()
{
// Policy override takes precedence
if (!string.IsNullOrWhiteSpace(PolicyManager.Current?.SettingsFolderLocation))
- return PolicyManager.Current.SettingsFolderLocation;
+ {
+ var policyPath = PolicyManager.Current.SettingsFolderLocation;
+
+ // Validate that the policy-provided path is rooted (absolute)
+ if (!Path.IsPathRooted(policyPath))
+ {
+ Log.Error($"Policy-provided SettingsFolderLocation is not an absolute path: {policyPath}. Falling back to default location.");
+ }
+ else
+ {
+ // Validate that the path doesn't contain invalid characters
+ try
+ {
+ // This will throw if the path contains invalid characters
+ _ = Path.GetFullPath(policyPath);
+ return policyPath;
+ }
+ catch (Exception ex)
+ {
+ Log.Error($"Policy-provided SettingsFolderLocation contains invalid characters: {policyPath}. Falling back to default location.", ex);
+ }
+ }
+ }
// Fall back to existing logic
return ConfigurationManager.Current.IsPortable
diff --git a/Website/docs/system-wide-policies.md b/Website/docs/system-wide-policies.md
index 56e85d6b5d..af3427efbe 100644
--- a/Website/docs/system-wide-policies.md
+++ b/Website/docs/system-wide-policies.md
@@ -137,11 +137,15 @@ See [Location](./settings/settings.md#location) for more details.
:::warning
When configuring a custom settings folder location, ensure:
+- The path **must be an absolute path** (e.g., `C:\\Path\\To\\Folder`, not `.\\RelativePath`)
- The path uses double backslashes (`\\`) in JSON format
+- The path does not contain invalid characters for the file system
- The application has read/write permissions to the specified directory
- The directory exists or the application has permissions to create it
- All users have appropriate access to the folder if using a shared location
+If the policy-provided path is invalid (not absolute or contains invalid characters), the application will log an error and fall back to the default location.
+
:::
## Future Policies
From 65e973245c5279bf8b68830adc75afb0a060df30 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 9 Feb 2026 20:13:45 +0000
Subject: [PATCH 04/25] Improve exception handling and documentation structure
Co-authored-by: BornToBeRoot <16019165+BornToBeRoot@users.noreply.github.com>
---
Source/NETworkManager.Settings/SettingsManager.cs | 8 ++++++--
Website/docs/system-wide-policies.md | 4 +++-
2 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/Source/NETworkManager.Settings/SettingsManager.cs b/Source/NETworkManager.Settings/SettingsManager.cs
index 1343bf2c81..f220b24587 100644
--- a/Source/NETworkManager.Settings/SettingsManager.cs
+++ b/Source/NETworkManager.Settings/SettingsManager.cs
@@ -92,14 +92,18 @@ public static string GetSettingsFolderLocation()
// Validate that the path doesn't contain invalid characters
try
{
- // This will throw if the path contains invalid characters
+ // This will throw ArgumentException or NotSupportedException if the path contains invalid characters
_ = Path.GetFullPath(policyPath);
return policyPath;
}
- catch (Exception ex)
+ catch (ArgumentException ex)
{
Log.Error($"Policy-provided SettingsFolderLocation contains invalid characters: {policyPath}. Falling back to default location.", ex);
}
+ catch (NotSupportedException ex)
+ {
+ Log.Error($"Policy-provided SettingsFolderLocation format is not supported: {policyPath}. Falling back to default location.", ex);
+ }
}
}
diff --git a/Website/docs/system-wide-policies.md b/Website/docs/system-wide-policies.md
index af3427efbe..c9126a5d51 100644
--- a/Website/docs/system-wide-policies.md
+++ b/Website/docs/system-wide-policies.md
@@ -32,7 +32,7 @@ The `config.json` file uses a simple JSON structure to define policy values. An
```
-**Example:**
+**Example with available policies:**
```json
{
@@ -41,6 +41,8 @@ The `config.json` file uses a simple JSON structure to define policy values. An
}
```
+For a complete list of available policies, see the [Available Policies](#available-policies) section below.
+
Property names generally follow the pattern `Section_SettingName` (see each setting's documentation). Ensure values use the correct JSON type (boolean, string, number, etc.).
:::note
From 114f86ce82bdeac838d65bfb6e846f19af996768 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 9 Feb 2026 20:14:31 +0000
Subject: [PATCH 05/25] Add SecurityException handling and fix documentation
formatting
Co-authored-by: BornToBeRoot <16019165+BornToBeRoot@users.noreply.github.com>
---
Source/NETworkManager.Settings/SettingsManager.cs | 6 +++++-
Website/docs/system-wide-policies.md | 2 +-
2 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/Source/NETworkManager.Settings/SettingsManager.cs b/Source/NETworkManager.Settings/SettingsManager.cs
index f220b24587..6a8c399a9a 100644
--- a/Source/NETworkManager.Settings/SettingsManager.cs
+++ b/Source/NETworkManager.Settings/SettingsManager.cs
@@ -92,7 +92,7 @@ public static string GetSettingsFolderLocation()
// Validate that the path doesn't contain invalid characters
try
{
- // This will throw ArgumentException or NotSupportedException if the path contains invalid characters
+ // This will throw ArgumentException, NotSupportedException, or SecurityException if the path is invalid
_ = Path.GetFullPath(policyPath);
return policyPath;
}
@@ -104,6 +104,10 @@ public static string GetSettingsFolderLocation()
{
Log.Error($"Policy-provided SettingsFolderLocation format is not supported: {policyPath}. Falling back to default location.", ex);
}
+ catch (System.Security.SecurityException ex)
+ {
+ Log.Error($"Insufficient permissions to access policy-provided SettingsFolderLocation: {policyPath}. Falling back to default location.", ex);
+ }
}
}
diff --git a/Website/docs/system-wide-policies.md b/Website/docs/system-wide-policies.md
index c9126a5d51..be39de8f05 100644
--- a/Website/docs/system-wide-policies.md
+++ b/Website/docs/system-wide-policies.md
@@ -32,7 +32,7 @@ The `config.json` file uses a simple JSON structure to define policy values. An
```
-**Example with available policies:**
+**Example:**
```json
{
From 92530c7e71484a91f8580b9bb9171a230ad95ae7 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 9 Feb 2026 20:15:20 +0000
Subject: [PATCH 06/25] Fix using statement and clarify path format
documentation
Co-authored-by: BornToBeRoot <16019165+BornToBeRoot@users.noreply.github.com>
---
Source/NETworkManager.Settings/SettingsManager.cs | 3 ++-
Website/docs/system-wide-policies.md | 4 ++--
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/Source/NETworkManager.Settings/SettingsManager.cs b/Source/NETworkManager.Settings/SettingsManager.cs
index 6a8c399a9a..343eac7ec2 100644
--- a/Source/NETworkManager.Settings/SettingsManager.cs
+++ b/Source/NETworkManager.Settings/SettingsManager.cs
@@ -5,6 +5,7 @@
using System;
using System.IO;
using System.Linq;
+using System.Security;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Xml.Serialization;
@@ -104,7 +105,7 @@ public static string GetSettingsFolderLocation()
{
Log.Error($"Policy-provided SettingsFolderLocation format is not supported: {policyPath}. Falling back to default location.", ex);
}
- catch (System.Security.SecurityException ex)
+ catch (SecurityException ex)
{
Log.Error($"Insufficient permissions to access policy-provided SettingsFolderLocation: {policyPath}. Falling back to default location.", ex);
}
diff --git a/Website/docs/system-wide-policies.md b/Website/docs/system-wide-policies.md
index be39de8f05..87aa09f229 100644
--- a/Website/docs/system-wide-policies.md
+++ b/Website/docs/system-wide-policies.md
@@ -139,8 +139,8 @@ See [Location](./settings/settings.md#location) for more details.
:::warning
When configuring a custom settings folder location, ensure:
-- The path **must be an absolute path** (e.g., `C:\\Path\\To\\Folder`, not `.\\RelativePath`)
-- The path uses double backslashes (`\\`) in JSON format
+- The path **must be an absolute path** (e.g., `C:\\Path\\To\\Folder` or `C:/Path/To/Folder`, not `.\\RelativePath`)
+- For Windows paths, use either double backslashes (`\\`) or forward slashes (`/`) in JSON format (both `C:\\Path\\Folder` and `C:/Path/Folder` are valid)
- The path does not contain invalid characters for the file system
- The application has read/write permissions to the specified directory
- The directory exists or the application has permissions to create it
From 41633bf1066accc33231f47e72e12b78f692d218 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 9 Feb 2026 20:16:04 +0000
Subject: [PATCH 07/25] Use consistent example path in documentation
Co-authored-by: BornToBeRoot <16019165+BornToBeRoot@users.noreply.github.com>
---
Website/docs/system-wide-policies.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Website/docs/system-wide-policies.md b/Website/docs/system-wide-policies.md
index 87aa09f229..c8c2861010 100644
--- a/Website/docs/system-wide-policies.md
+++ b/Website/docs/system-wide-policies.md
@@ -37,7 +37,7 @@ The `config.json` file uses a simple JSON structure to define policy values. An
```json
{
"Update_CheckForUpdatesAtStartup": false,
- "SettingsFolderLocation": "C:\\ProgramData\\NETworkManager\\Settings"
+ "SettingsFolderLocation": "C:\\CustomPath\\NETworkManager\\Settings"
}
```
From a58b7e091e6cbb75f4e2c31a87937b16c44388f4 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 9 Feb 2026 20:35:06 +0000
Subject: [PATCH 08/25] Address review feedback: validate directory, update
docs, add admin indicator
Co-authored-by: BornToBeRoot <16019165+BornToBeRoot@users.noreply.github.com>
---
.../SettingsManager.cs | 13 ++++-
.../ViewModels/SettingsSettingsViewModel.cs | 5 ++
.../Views/SettingsSettingsView.xaml | 15 ++++++
Website/docs/settings/settings.md | 20 +++++++-
Website/docs/system-wide-policies.md | 50 -------------------
5 files changed, 49 insertions(+), 54 deletions(-)
diff --git a/Source/NETworkManager.Settings/SettingsManager.cs b/Source/NETworkManager.Settings/SettingsManager.cs
index 343eac7ec2..76961df19b 100644
--- a/Source/NETworkManager.Settings/SettingsManager.cs
+++ b/Source/NETworkManager.Settings/SettingsManager.cs
@@ -94,8 +94,17 @@ public static string GetSettingsFolderLocation()
try
{
// This will throw ArgumentException, NotSupportedException, or SecurityException if the path is invalid
- _ = Path.GetFullPath(policyPath);
- return policyPath;
+ var fullPath = Path.GetFullPath(policyPath);
+
+ // Check if the path is a directory (not a file)
+ if (File.Exists(fullPath))
+ {
+ Log.Error($"Policy-provided SettingsFolderLocation is a file, not a directory: {policyPath}. Falling back to default location.");
+ }
+ else
+ {
+ return fullPath;
+ }
}
catch (ArgumentException ex)
{
diff --git a/Source/NETworkManager/ViewModels/SettingsSettingsViewModel.cs b/Source/NETworkManager/ViewModels/SettingsSettingsViewModel.cs
index 330f98e21e..aa41762eb5 100644
--- a/Source/NETworkManager/ViewModels/SettingsSettingsViewModel.cs
+++ b/Source/NETworkManager/ViewModels/SettingsSettingsViewModel.cs
@@ -31,6 +31,11 @@ public string Location
}
}
+ ///
+ /// Gets whether the settings folder location is managed by system-wide policy.
+ ///
+ public bool IsLocationManagedByPolicy => !string.IsNullOrWhiteSpace(PolicyManager.Current?.SettingsFolderLocation);
+
private bool _isDailyBackupEnabled;
public bool IsDailyBackupEnabled
diff --git a/Source/NETworkManager/Views/SettingsSettingsView.xaml b/Source/NETworkManager/Views/SettingsSettingsView.xaml
index b51f7fe9e6..769491d08d 100644
--- a/Source/NETworkManager/Views/SettingsSettingsView.xaml
+++ b/Source/NETworkManager/Views/SettingsSettingsView.xaml
@@ -7,12 +7,27 @@
xmlns:iconPacks="http://metro.mahapps.com/winfx/xaml/iconpacks"
xmlns:viewModels="clr-namespace:NETworkManager.ViewModels"
xmlns:localization="clr-namespace:NETworkManager.Localization.Resources;assembly=NETworkManager.Localization"
+ xmlns:converters="clr-namespace:NETworkManager.Converters;assembly=NETworkManager.Converters"
mc:Ignorable="d" Loaded="UserControl_Loaded"
d:DataContext="{d:DesignInstance viewModels:SettingsSettingsViewModel}">
+
+
+
+
+
+
+
+
+
+
+
-
+
Date: Mon, 16 Feb 2026 02:29:59 +0100
Subject: [PATCH 14/25] Feature: UI
---
.../Resources/Strings.Designer.cs | 20 ++++++++++++
.../Resources/Strings.resx | 8 +++++
.../ViewModels/SettingsSettingsViewModel.cs | 31 +++++++++++++------
.../Views/SettingsSettingsView.xaml | 7 +++--
4 files changed, 54 insertions(+), 12 deletions(-)
diff --git a/Source/NETworkManager.Localization/Resources/Strings.Designer.cs b/Source/NETworkManager.Localization/Resources/Strings.Designer.cs
index 2b2889dfbd..6510d5f2b3 100644
--- a/Source/NETworkManager.Localization/Resources/Strings.Designer.cs
+++ b/Source/NETworkManager.Localization/Resources/Strings.Designer.cs
@@ -1455,6 +1455,26 @@ public static string Change {
}
}
+ ///
+ /// Sucht eine lokalisierte Zeichenfolge, die Change location? ähnelt.
+ ///
+ public static string ChangeLocationQuestion {
+ get {
+ return ResourceManager.GetString("ChangeLocationQuestion", resourceCulture);
+ }
+ }
+
+ ///
+ /// Sucht eine lokalisierte Zeichenfolge, die The location is changed and the application is restarted afterwards.
+ ///
+ ///You can copy the “settings.json” file from "{0}" to "{1}" to migrate your previous settings, if necessary. The application must be closed for this to prevent the settings from being overwritten. ähnelt.
+ ///
+ public static string ChangeLocationSettingsMessage {
+ get {
+ return ResourceManager.GetString("ChangeLocationSettingsMessage", resourceCulture);
+ }
+ }
+
///
/// Sucht eine lokalisierte Zeichenfolge, die Changelog ähnelt.
///
diff --git a/Source/NETworkManager.Localization/Resources/Strings.resx b/Source/NETworkManager.Localization/Resources/Strings.resx
index d2d3adada4..db5f80a6fa 100644
--- a/Source/NETworkManager.Localization/Resources/Strings.resx
+++ b/Source/NETworkManager.Localization/Resources/Strings.resx
@@ -3975,6 +3975,14 @@ If you click Cancel, the profile file will remain unencrypted.
The default path is restored and the application is restarted afterwards.
+You can copy the “settings.json” file from "{0}" to "{1}" to migrate your previous settings, if necessary. The application must be closed for this to prevent the settings from being overwritten.
+
+
+ Change location?
+
+
+ The location is changed and the application is restarted afterwards.
+
You can copy the “settings.json” file from "{0}" to "{1}" to migrate your previous settings, if necessary. The application must be closed for this to prevent the settings from being overwritten.
\ No newline at end of file
diff --git a/Source/NETworkManager/ViewModels/SettingsSettingsViewModel.cs b/Source/NETworkManager/ViewModels/SettingsSettingsViewModel.cs
index 7f6ae17c21..533da2cc0e 100644
--- a/Source/NETworkManager/ViewModels/SettingsSettingsViewModel.cs
+++ b/Source/NETworkManager/ViewModels/SettingsSettingsViewModel.cs
@@ -205,22 +205,29 @@ public void SetLocationPathFromDragDrop(string path)
Location = path;
}
- public ICommand ChangeLocationCommand => new RelayCommand(_ => ChangeLocationAction());
+ public ICommand ChangeLocationCommand => new RelayCommand(_ => ChangeLocationAction().ConfigureAwait(false));
private async Task ChangeLocationAction()
{
- /*
- var result = await DialogHelper.ShowConfirmationMessageAsync(Application.Current.MainWindow,
- Strings.ChangeSettingsLocationQuestion,
- Strings.SettingsLocationWillBeChangedAndApplicationWillBeRestartedMessage,
- ChildWindowIcon.Question,
- Strings.Apply);
+ var result = await DialogHelper.ShowConfirmationMessageAsync(Application.Current.MainWindow,
+ Strings.ChangeLocationQuestion,
+ string.Format(Strings.ChangeLocationSettingsMessage, SettingsManager.GetSettingsFolderLocation(), Location),
+ ChildWindowIcon.Question,
+ Strings.Change);
+
+ if (!result)
+ return;
+
+ // Save settings at the current location before changing it to prevent
+ // unintended saves to the new location (e.g., triggered by background timer or the app close & restart).
+ SettingsManager.Save();
+ // Set new location
+ LocalSettingsManager.Current.SettingsFolderLocation = Location;
LocalSettingsManager.Save();
// Restart the application
(Application.Current.MainWindow as MainWindow)?.RestartApplication();
- */
}
public ICommand RestoreDefaultLocationCommand => new RelayCommand(_ => RestoreDefaultLocationActionAsync().ConfigureAwait(false));
@@ -229,15 +236,19 @@ private async Task RestoreDefaultLocationActionAsync()
{
var result = await DialogHelper.ShowConfirmationMessageAsync(Application.Current.MainWindow,
Strings.RestoreDefaultLocationQuestion,
- string.Format(Strings.RestoreDefaultLocationSettingsMessage, SettingsManager.GetSettingsFolderLocation(),SettingsManager.GetDefaultSettingsFolderLocation()),
+ string.Format(Strings.RestoreDefaultLocationSettingsMessage, SettingsManager.GetSettingsFolderLocation(), SettingsManager.GetDefaultSettingsFolderLocation()),
ChildWindowIcon.Question,
Strings.Restore);
if (!result)
return;
- LocalSettingsManager.Current.SettingsFolderLocation = null;
+ // Save settings at the current location before changing it to prevent
+ // unintended saves to the new location (e.g., triggered by background timer or the app close & restart).
+ SettingsManager.Save();
+ // Clear custom location to revert to default
+ LocalSettingsManager.Current.SettingsFolderLocation = null;
LocalSettingsManager.Save();
// Restart the application
diff --git a/Source/NETworkManager/Views/SettingsSettingsView.xaml b/Source/NETworkManager/Views/SettingsSettingsView.xaml
index d3a3134561..5b2ead09f5 100644
--- a/Source/NETworkManager/Views/SettingsSettingsView.xaml
+++ b/Source/NETworkManager/Views/SettingsSettingsView.xaml
@@ -68,7 +68,10 @@
+ Command="{Binding ChangeLocationCommand}"
+ Visibility="{Binding IsLocationChanged, Converter={StaticResource BooleanToVisibilityCollapsedConverter}}"
+ HorizontalAlignment="Left"
+ Margin="0,0,10,0" >
@@ -81,7 +84,7 @@
From 360ad30d3b68c1a329c89d63903bebdb645987f4 Mon Sep 17 00:00:00 2001
From: BornToBeRoot <16019165+BornToBeRoot@users.noreply.github.com>
Date: Wed, 18 Feb 2026 00:42:34 +0100
Subject: [PATCH 15/25] Feature: Env var for folder
---
.../Resources/Strings.Designer.cs | 9 +++
.../Resources/Strings.resx | 3 +
.../SettingsManager.cs | 5 +-
.../NETworkManager.Utilities/RegexHelper.cs | 37 ++++++----
...ryPathWithEnvironmentVariablesValidator.cs | 31 +++++----
Source/NETworkManager/NETworkManager.csproj | 7 +-
.../ViewModels/SettingsSettingsViewModel.cs | 68 +++++++++++++++++--
.../Views/SettingsSettingsView.xaml | 14 +++-
Website/docs/settings/settings.md | 2 +-
9 files changed, 133 insertions(+), 43 deletions(-)
diff --git a/Source/NETworkManager.Localization/Resources/Strings.Designer.cs b/Source/NETworkManager.Localization/Resources/Strings.Designer.cs
index 6510d5f2b3..40ef350d30 100644
--- a/Source/NETworkManager.Localization/Resources/Strings.Designer.cs
+++ b/Source/NETworkManager.Localization/Resources/Strings.Designer.cs
@@ -3587,6 +3587,15 @@ public static string EnterValidFilePath {
}
}
+ ///
+ /// Sucht eine lokalisierte Zeichenfolge, die Enter a valid folder path! ähnelt.
+ ///
+ public static string EnterValidFolderPath {
+ get {
+ return ResourceManager.GetString("EnterValidFolderPath", resourceCulture);
+ }
+ }
+
///
/// Sucht eine lokalisierte Zeichenfolge, die Enter a valid hostname! ähnelt.
///
diff --git a/Source/NETworkManager.Localization/Resources/Strings.resx b/Source/NETworkManager.Localization/Resources/Strings.resx
index db5f80a6fa..ad2eb07c93 100644
--- a/Source/NETworkManager.Localization/Resources/Strings.resx
+++ b/Source/NETworkManager.Localization/Resources/Strings.resx
@@ -3985,4 +3985,7 @@ You can copy the “settings.json” file from "{0}" to "{1}" to migrate your pr
You can copy the “settings.json” file from "{0}" to "{1}" to migrate your previous settings, if necessary. The application must be closed for this to prevent the settings from being overwritten.
+
+ Enter a valid folder path!
+
\ No newline at end of file
diff --git a/Source/NETworkManager.Settings/SettingsManager.cs b/Source/NETworkManager.Settings/SettingsManager.cs
index a8d812fa4f..b763dac185 100644
--- a/Source/NETworkManager.Settings/SettingsManager.cs
+++ b/Source/NETworkManager.Settings/SettingsManager.cs
@@ -139,6 +139,9 @@ public static string GetPortableSettingsFolderLocation()
/// The validated full path if valid; otherwise, null.
private static string ValidateSettingsFolderPath(string path, string pathSource, string fallbackMessage)
{
+ // Expand environment variables first (e.g. %userprofile%\settings -> C:\Users\...\settings)
+ path = Environment.ExpandEnvironmentVariables(path);
+
// Validate that the path is rooted (absolute)
if (!Path.IsPathRooted(path))
{
@@ -159,7 +162,7 @@ private static string ValidateSettingsFolderPath(string path, string pathSource,
return null;
}
- return fullPath;
+ return fullPath.TrimEnd('\\');
}
catch (ArgumentException ex)
{
diff --git a/Source/NETworkManager.Utilities/RegexHelper.cs b/Source/NETworkManager.Utilities/RegexHelper.cs
index ec5d2385a1..4935e0ec41 100644
--- a/Source/NETworkManager.Utilities/RegexHelper.cs
+++ b/Source/NETworkManager.Utilities/RegexHelper.cs
@@ -85,6 +85,30 @@ public static partial class RegexHelper
[GeneratedRegex($@"^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|{SpecialRangeRegex})\.){{3}}((?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)|{SpecialRangeRegex})$")]
public static partial Regex IPv4AddressSpecialRangeRegex();
+ ///
+ /// Provides a compiled regular expression that matches valid hostnames or fully qualified domain names (FQDNs) like
+ /// server-01 or server-01.example.com.
+ ///
+ /// A instance that matches valid hostnames or FQDNs.
+ [GeneratedRegex($@"^{HostnameOrDomainValues}$")]
+ public static partial Regex HostnameOrDomainRegex();
+
+ ///
+ /// Creates a regular expression that matches a local directory path or one using environment variables,
+ /// like "C:\Temp", "C:\My Settings", "%AppData%\settings".
+ ///
+ /// A instance that matches valid local directory paths.
+ [GeneratedRegex($@"^(?:%[^%]+%|[a-zA-Z]\:)(\\[a-zA-Z0-9_\-\s\.]+)+\\?$")]
+ public static partial Regex DirectoryPathWithEnvironmentVariablesRegex();
+
+ ///
+ /// Creates a regular expression that matches a UNC path like "\\server\share", "\\server\c$\settings".
+ /// The share name may end with $ for hidden shares.
+ ///
+ /// A instance that matches valid UNC paths.
+ [GeneratedRegex($@"^\\\\[a-zA-Z0-9_\-\.]+(\\[a-zA-Z0-9_\-\s\.]+\$?)(\\[a-zA-Z0-9_\-\s\.]+)*\\?$")]
+ public static partial Regex UncPathRegex();
+
// Match a MAC-Address 000000000000 00:00:00:00:00:00, 00-00-00-00-00-00-00 or 0000.0000.0000
public const string MACAddressRegex =
@"^^[A-Fa-f0-9]{12}$|^[A-Fa-f0-9]{2}(:|-){1}[A-Fa-f0-9]{2}(:|-){1}[A-Fa-f0-9]{2}(:|-){1}[A-Fa-f0-9]{2}(:|-){1}[A-Fa-f0-9]{2}(:|-){1}[A-Fa-f0-9]{2}$|^[A-Fa-f0-9]{4}.[A-Fa-f0-9]{4}.[A-Fa-f0-9]{4}$$";
@@ -107,16 +131,6 @@ public static partial class RegexHelper
public const string SpecialRangeRegex =
@"\[((?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)|((?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)-(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)))([,]((?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)|((?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)-(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))))*\]";
-
-
- ///
- /// Provides a compiled regular expression that matches valid hostnames or fully qualified domain names (FQDNs) like
- /// server-01 or server-01.example.com.
- ///
- /// A instance that matches valid hostnames or FQDNs.
- [GeneratedRegex($@"^{HostnameOrDomainValues}$")]
- public static partial Regex HostnameOrDomainRegex();
-
// Match a hostname with cidr like server-01.example.com/24
public const string HostnameOrDomainWithCidrRegex = $@"^{HostnameOrDomainValues}\/{CidrRegexValues}$";
@@ -134,9 +148,6 @@ public static partial class RegexHelper
// Match a port between 1-65535
public const string PortRegex = $@"^{PortValues}$";
- // Match any filepath (like "c:\temp\") --> https://www.codeproject.com/Tips/216238/Regular-Expression-to-Validate-File-Path-and-Exten
- public const string FilePathRegex = @"^(?:[\w]\:|\\)(\\[a-z_\-\s0-9\.]+)+$";
-
// Match any fullname (like "c:\temp\test.txt") --> https://www.codeproject.com/Tips/216238/Regular-Expression-to-Validate-File-Path-and-Exten
public const string FullNameRegex =
@"^(?:[\w]\:|\\)(\\[a-zA-Z0-9_\-\s\.()~!@#$%^&=+';,{}\[\]]+)+\.[a-zA-z0-9]{1,4}$";
diff --git a/Source/NETworkManager.Validators/DirectoryPathWithEnvironmentVariablesValidator.cs b/Source/NETworkManager.Validators/DirectoryPathWithEnvironmentVariablesValidator.cs
index 1d7ead626e..c532afb9bb 100644
--- a/Source/NETworkManager.Validators/DirectoryPathWithEnvironmentVariablesValidator.cs
+++ b/Source/NETworkManager.Validators/DirectoryPathWithEnvironmentVariablesValidator.cs
@@ -1,6 +1,4 @@
-using System;
-using System.Globalization;
-using System.Text.RegularExpressions;
+using System.Globalization;
using System.Windows.Controls;
using NETworkManager.Localization.Resources;
using NETworkManager.Utilities;
@@ -8,24 +6,27 @@
namespace NETworkManager.Validators;
///
-/// Check if the string is a valid directory path (like "C:\Temp\" or "%AppData%\Temp"). The directory path does not
-/// have to exist on the local system.
+/// Provides a validation rule that determines whether a value represents a syntactically valid directory path,
+/// supporting the inclusion of environment variable references like %UserProfile%.
///
public class DirectoryPathWithEnvironmentVariablesValidator : ValidationRule
{
///
- /// Check if the string is a valid directory path (like "C:\Temp\" or "%AppData%\Temp"). The directory path does not
- /// have to exist on the local system.
- ///
- /// Directory path like "C:\test" or "%AppData%\test".
- /// Culture to use for validation.
- /// True if the directory path is valid.
+ /// Validates whether the specified value represents a valid directory path, allowing for the inclusion of
+ /// environment variables like %UserProfile%.
+ ///
+ /// The value to validate as a directory path. May include environment variable references. Can be a string or an
+ /// object convertible to a string.
+ /// The culture-specific information relevant to the validation process. This parameter is not used in this
+ /// implementation.
+ /// A ValidationResult that indicates whether the value is a valid directory path. Returns
+ /// ValidationResult.ValidResult if the value is valid; otherwise, returns a ValidationResult with an error message.
public override ValidationResult Validate(object value, CultureInfo cultureInfo)
{
- var path = Environment.ExpandEnvironmentVariables((string)value);
+ var path = $"{value}";
- return new Regex(RegexHelper.FilePathRegex, RegexOptions.IgnoreCase).IsMatch(path)
+ return RegexHelper.DirectoryPathWithEnvironmentVariablesRegex().IsMatch(path) || RegexHelper.UncPathRegex().IsMatch(path)
? ValidationResult.ValidResult
- : new ValidationResult(false, Strings.EnterValidFilePath);
+ : new ValidationResult(false, Strings.EnterValidFolderPath);
}
-}
\ No newline at end of file
+}
diff --git a/Source/NETworkManager/NETworkManager.csproj b/Source/NETworkManager/NETworkManager.csproj
index 3dee3d3535..a61640f1f5 100644
--- a/Source/NETworkManager/NETworkManager.csproj
+++ b/Source/NETworkManager/NETworkManager.csproj
@@ -8,10 +8,6 @@
win-x64x64false
-
sdktruetrue
@@ -74,8 +70,7 @@
-
-
+
diff --git a/Source/NETworkManager/ViewModels/SettingsSettingsViewModel.cs b/Source/NETworkManager/ViewModels/SettingsSettingsViewModel.cs
index 533da2cc0e..fc635e8570 100644
--- a/Source/NETworkManager/ViewModels/SettingsSettingsViewModel.cs
+++ b/Source/NETworkManager/ViewModels/SettingsSettingsViewModel.cs
@@ -13,6 +13,9 @@ namespace NETworkManager.ViewModels;
public class SettingsSettingsViewModel : ViewModelBase
{
#region Variables
+ ///
+ /// Gets or sets the action to execute when the associated object is closed.
+ ///
public Action CloseAction { get; set; }
///
@@ -143,6 +146,9 @@ public int MaximumNumberOfBackups
#region Constructor, LoadSettings
+ ///
+ /// Initializes a new instance of the class and loads the current settings.
+ ///
public SettingsSettingsViewModel()
{
_isLoading = true;
@@ -152,14 +158,13 @@ public SettingsSettingsViewModel()
_isLoading = false;
}
+ ///
+ /// Loads the application settings from the current settings folder location.
+ ///
private void LoadSettings()
{
Location = SettingsManager.GetSettingsFolderLocation();
IsDefaultLocation = string.Equals(Location, SettingsManager.GetDefaultSettingsFolderLocation(), StringComparison.OrdinalIgnoreCase);
-
- Debug.WriteLine(Location);
- Debug.WriteLine(SettingsManager.GetDefaultSettingsFolderLocation());
-
IsDailyBackupEnabled = SettingsManager.Current.Settings_IsDailyBackupEnabled;
MaximumNumberOfBackups = SettingsManager.Current.Settings_MaximumNumberOfBackups;
}
@@ -168,15 +173,27 @@ private void LoadSettings()
#region ICommands & Actions
+ ///
+ /// Gets the command that opens a location when executed.
+ ///
public ICommand OpenLocationCommand => new RelayCommand(_ => OpenLocationAction());
+ ///
+ /// Opens the settings folder location in Windows Explorer.
+ ///
private static void OpenLocationAction()
{
Process.Start("explorer.exe", SettingsManager.GetSettingsFolderLocation());
}
+ ///
+ /// Gets the command that resets the application settings to their default values.
+ ///
public ICommand ResetSettingsCommand => new RelayCommand(_ => ResetSettingsAction());
+ ///
+ /// Resets the application settings to their default values.
+ ///
private void ResetSettingsAction()
{
ResetSettings().ConfigureAwait(false);
@@ -185,8 +202,18 @@ private void ResetSettingsAction()
#endregion
#region Methods
+ ///
+ /// Gets the command that opens the location folder selection dialog.
+ ///
public ICommand BrowseLocationFolderCommand => new RelayCommand(p => BrowseLocationFolderAction());
+ ///
+ /// Opens a dialog that allows the user to select a folder location and updates the Location property with the
+ /// selected path if the user confirms the selection.
+ ///
+ /// If the Location property is set to a valid directory path, it is pre-selected in the dialog.
+ /// This method does not return a value and is intended for use in a user interface context where folder selection
+ /// is required.
private void BrowseLocationFolderAction()
{
using var dialog = new System.Windows.Forms.FolderBrowserDialog();
@@ -200,13 +227,28 @@ private void BrowseLocationFolderAction()
Location = dialog.SelectedPath;
}
+ ///
+ /// Sets the location path based on the provided drag-and-drop input.
+ ///
+ /// The path to set as the location. This value cannot be null or empty.
public void SetLocationPathFromDragDrop(string path)
{
Location = path;
}
+ ///
+ /// Gets the command that initiates the action to change the location.
+ ///
public ICommand ChangeLocationCommand => new RelayCommand(_ => ChangeLocationAction().ConfigureAwait(false));
+ ///
+ /// Prompts the user to confirm and then changes the location of the application's settings folder.
+ ///
+ /// This method displays a confirmation dialog to the user before changing the settings folder
+ /// location. If the user confirms, it saves the current settings, updates the settings folder location, and
+ /// restarts the application to apply the changes. No action is taken if the user cancels the confirmation
+ /// dialog.
+ /// A task that represents the asynchronous operation.
private async Task ChangeLocationAction()
{
var result = await DialogHelper.ShowConfirmationMessageAsync(Application.Current.MainWindow,
@@ -230,8 +272,19 @@ private async Task ChangeLocationAction()
(Application.Current.MainWindow as MainWindow)?.RestartApplication();
}
+ ///
+ /// Gets the command that restores the default location settings asynchronously.
+ ///
public ICommand RestoreDefaultLocationCommand => new RelayCommand(_ => RestoreDefaultLocationActionAsync().ConfigureAwait(false));
+ ///
+ /// Restores the application's settings folder location to the default path after obtaining user confirmation.
+ ///
+ /// This method prompts the user to confirm the restoration of the default settings location. If
+ /// the user confirms, it saves the current settings, clears any custom location, and restarts the application to
+ /// apply the changes. Use this method when you want to revert to the default settings folder and ensure all changes
+ /// are properly saved and applied.
+ /// A task that represents the asynchronous operation.
private async Task RestoreDefaultLocationActionAsync()
{
var result = await DialogHelper.ShowConfirmationMessageAsync(Application.Current.MainWindow,
@@ -255,6 +308,13 @@ private async Task RestoreDefaultLocationActionAsync()
(Application.Current.MainWindow as MainWindow)?.RestartApplication();
}
+ ///
+ /// Resets the application settings to their default values and restarts the application after user confirmation.
+ ///
+ /// Displays a confirmation dialog to the user before proceeding. If the user confirms, the
+ /// settings are reinitialized to their defaults and the application is restarted. No action is taken if the user
+ /// cancels the confirmation dialog.
+ /// A task that represents the asynchronous operation.
private async Task ResetSettings()
{
var result = await DialogHelper.ShowConfirmationMessageAsync(Application.Current.MainWindow,
diff --git a/Source/NETworkManager/Views/SettingsSettingsView.xaml b/Source/NETworkManager/Views/SettingsSettingsView.xaml
index 5b2ead09f5..d1db5b42be 100644
--- a/Source/NETworkManager/Views/SettingsSettingsView.xaml
+++ b/Source/NETworkManager/Views/SettingsSettingsView.xaml
@@ -38,11 +38,11 @@
-
+
@@ -67,11 +67,19 @@
-
+
+
+
diff --git a/Website/docs/settings/settings.md b/Website/docs/settings/settings.md
index c08cf47f3d..7b2a95337d 100644
--- a/Website/docs/settings/settings.md
+++ b/Website/docs/settings/settings.md
@@ -24,7 +24,7 @@ This setting can be controlled by administrators using a system-wide policy. See
**Policy Property:** `SettingsFolderLocation`
**Values:**
-- Absolute path (e.g., `C:\\CustomPath\\NETworkManager\\Settings`) - Force a custom settings folder location for all users
+- Path like `C:\\Path\\To\\Settings` or `%UserProfile%\\NETworkManager\\Settings` - Force a custom settings folder location for all users
- Omit the property - Allow the default location logic to apply (portable vs. non-portable)
**Example:**
From fedc544b77579c2e9a3440fa2eb3033e4ee3d6a6 Mon Sep 17 00:00:00 2001
From: BornToBeRoot <16019165+BornToBeRoot@users.noreply.github.com>
Date: Wed, 18 Feb 2026 01:18:21 +0100
Subject: [PATCH 16/25] Docs: Add some docs
---
.../LocalSettingsManager.cs | 2 +-
Website/docs/changelog/next-release.md | 15 +++++++++++++--
Website/docs/settings/settings.md | 18 ++++++++++++++----
Website/docs/settings/update.md | 6 ++++++
4 files changed, 34 insertions(+), 7 deletions(-)
diff --git a/Source/NETworkManager.Settings/LocalSettingsManager.cs b/Source/NETworkManager.Settings/LocalSettingsManager.cs
index c8fd3cc983..011a1bae1d 100644
--- a/Source/NETworkManager.Settings/LocalSettingsManager.cs
+++ b/Source/NETworkManager.Settings/LocalSettingsManager.cs
@@ -99,7 +99,7 @@ public static void Load()
return;
}
-
+
Initialize();
}
diff --git a/Website/docs/changelog/next-release.md b/Website/docs/changelog/next-release.md
index 6fdd01caf2..df53c6d7e7 100644
--- a/Website/docs/changelog/next-release.md
+++ b/Website/docs/changelog/next-release.md
@@ -38,14 +38,25 @@ Release date: **xx.xx.2025**
Starting with this release, new profile and settings files are created in `JSON` format. Existing `XML` files will be converted automatically on first load after upgrading. Automatic support for the migration will be provided until at least `2027`; after that only `JSON` files will be supported and very old installations may require an interim update.
The migration process creates a backup of the original files in the `Backups` subfolder of the settings and profiles directories. You can restore the originals from that folder if needed (they will work with the privous version), but it's **recommended to make a separate backup of your profile and settings files before updating**. If you encounter any issues during or after the migration, please report them via the [issue tracker](https://github.com/BornToBeRoot/NETworkManager/issues/new/choose).
-
+
:::
## What's new?
+- [System-Wide Policies](../system-wide-policies.md) for enterprise deployment and management. Administrators can now configure system-wide policies via a `config.json` file in the application directory to control specific settings for all users. This allows for centralized management of application behavior in enterprise environments. [#3313](https://github.com/BornToBeRoot/NETworkManager/pull/3313) [#3326](https://github.com/BornToBeRoot/NETworkManager/pull/3326)
+
+ Currently supported policies include (more will be added in future releases):
+ - Check for updates at startup (see [Update > Check for updates at startup](../settings/update.md#check-for-updates-at-startup) documentation for more information)
+ - Settings folder location (see [Settings > Location](../settings/settings.md#location) documentation for more information)
+
+ :::note
+
+ If you have specific requirements for system-wide policies in your organization, please submit a feature request via the [GitHub issue tracker](https://github.com/BornToBeRoot/NETworkManager/issues/new/choose).
+
+ :::
+
- New language Ukrainian (`uk-UA`) has been added. Thanks to [@vadickkt](https://github.com/vadickkt) [#3240](https://github.com/BornToBeRoot/NETworkManager/pull/3240)
- Migrated all dialogs to child windows for improved usability and accessibility. [#3271](https://github.com/BornToBeRoot/NETworkManager/pull/3271)
-- System-wide policies can now be configured via a `config.json` file in the application directory to control settings for all users. Currently supports controlling the "Check for updates at startup" setting. This is useful for enterprise deployments where administrators need centralized control over update behavior. See [System-Wide Policies](../system-wide-policies.md) documentation for more information. [#3313](https://github.com/BornToBeRoot/NETworkManager/pull/3313)
**DNS Lookup**
diff --git a/Website/docs/settings/settings.md b/Website/docs/settings/settings.md
index 7b2a95337d..3af08fd661 100644
--- a/Website/docs/settings/settings.md
+++ b/Website/docs/settings/settings.md
@@ -19,22 +19,30 @@ Folder where the application settings are stored.
:::info System-Wide Policy
+
+Click to expand
+
This setting can be controlled by administrators using a system-wide policy. See [System-Wide Policies](../system-wide-policies.md) for more information.
**Policy Property:** `SettingsFolderLocation`
**Values:**
-- Path like `C:\\Path\\To\\Settings` or `%UserProfile%\\NETworkManager\\Settings` - Force a custom settings folder location for all users
-- Omit the property - Allow the default location logic to apply (portable vs. non-portable)
+
+- Absolute path (e.g., `C:\\Path\\To\\Settings`)
+- Path with environment variables (e.g., `%UserProfile%\\NETworkManager\\Settings`)
+- UNC path (e.g., `\\\\server\\share$\\NETworkManager\\Settings`)
+- Omit the property to allow the default location logic to apply (portable vs. non-portable)
**Example:**
```json
{
- "SettingsFolderLocation": "C:\\CustomPath\\NETworkManager\\Settings"
+ "SettingsFolderLocation": "%UserProfile%\\NETworkManager\\Settings"
}
```
+
+
:::
:::note
@@ -44,12 +52,14 @@ It is strongly recommended to regularly back up your settings files.
**Automatic backups**
NETworkManager automatically creates a backup of the settings files before applying any changes. See [Create daily backup](#create-daily-backup) and [Maximum number of backups](#maximum-number-of-backups) for configuration options.
+
- Location: `Settings\Backups` subfolder
- Naming: timestamped (e.g. `yyyyMMddHHmmss_Settings.json`)
- Frequency: **once per day** at most (even if multiple changes occur)
- Retention: keeps the **10 most recent backups** (default)
-**Restoring settings**
+**Restoring settings**
+
1. Completely close NETworkManager
2. Locate the desired backup in `Settings\Backups`
3. Copy the file(s) back to the original folder (overwriting existing files)
diff --git a/Website/docs/settings/update.md b/Website/docs/settings/update.md
index 9c006a108b..bf1c5dd5e8 100644
--- a/Website/docs/settings/update.md
+++ b/Website/docs/settings/update.md
@@ -14,11 +14,15 @@ Check for new program versions on GitHub when the application is launched.
:::info System-Wide Policy
+
+Click to expand
+
This setting can be controlled by administrators using a system-wide policy. See [System-Wide Policies](../system-wide-policies.md) for more information.
**Policy Property:** `Update_CheckForUpdatesAtStartup`
**Values:**
+
- `true` - Force enable automatic update checks at startup for all users
- `false` - Force disable automatic update checks at startup for all users
- Omit the property - Allow users to control this setting themselves
@@ -31,6 +35,8 @@ This setting can be controlled by administrators using a system-wide policy. See
}
```
+
+
:::
:::note
From 8d83d189c61d7a583866bed3d0542f0b1852b785 Mon Sep 17 00:00:00 2001
From: BornToBeRoot <16019165+BornToBeRoot@users.noreply.github.com>
Date: Wed, 18 Feb 2026 01:22:28 +0100
Subject: [PATCH 17/25] Chore: Update packages
---
Source/NETworkManager.Models/NETworkManager.Models.csproj | 4 ++--
Source/NETworkManager/NETworkManager.csproj | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/Source/NETworkManager.Models/NETworkManager.Models.csproj b/Source/NETworkManager.Models/NETworkManager.Models.csproj
index 230de2c91a..c913dd5488 100644
--- a/Source/NETworkManager.Models/NETworkManager.Models.csproj
+++ b/Source/NETworkManager.Models/NETworkManager.Models.csproj
@@ -27,7 +27,7 @@
-
+
@@ -36,7 +36,7 @@
-
+
diff --git a/Source/NETworkManager/NETworkManager.csproj b/Source/NETworkManager/NETworkManager.csproj
index a61640f1f5..6a6a3a04a2 100644
--- a/Source/NETworkManager/NETworkManager.csproj
+++ b/Source/NETworkManager/NETworkManager.csproj
@@ -58,7 +58,7 @@
-
+
@@ -69,7 +69,7 @@
-
+
From 257efe925a5bde9347693aa00948c83ae92380b2 Mon Sep 17 00:00:00 2001
From: BornToBeRoot <16019165+BornToBeRoot@users.noreply.github.com>
Date: Wed, 18 Feb 2026 01:34:24 +0100
Subject: [PATCH 18/25] Update
Source/NETworkManager.Settings/SettingsManager.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
---
Source/NETworkManager.Settings/SettingsManager.cs | 1 -
1 file changed, 1 deletion(-)
diff --git a/Source/NETworkManager.Settings/SettingsManager.cs b/Source/NETworkManager.Settings/SettingsManager.cs
index b763dac185..523a70561c 100644
--- a/Source/NETworkManager.Settings/SettingsManager.cs
+++ b/Source/NETworkManager.Settings/SettingsManager.cs
@@ -9,7 +9,6 @@
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Xml.Serialization;
-using Windows.Gaming.Input.Custom;
namespace NETworkManager.Settings;
From c7c743a3b949f92daf3f49057f97d705cfdc1b4e Mon Sep 17 00:00:00 2001
From: BornToBeRoot <16019165+BornToBeRoot@users.noreply.github.com>
Date: Wed, 18 Feb 2026 01:36:39 +0100
Subject: [PATCH 19/25] Update
Source/NETworkManager/ViewModels/SettingsSettingsViewModel.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
---
Source/NETworkManager/ViewModels/SettingsSettingsViewModel.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Source/NETworkManager/ViewModels/SettingsSettingsViewModel.cs b/Source/NETworkManager/ViewModels/SettingsSettingsViewModel.cs
index fc635e8570..e14ee3639c 100644
--- a/Source/NETworkManager/ViewModels/SettingsSettingsViewModel.cs
+++ b/Source/NETworkManager/ViewModels/SettingsSettingsViewModel.cs
@@ -76,7 +76,7 @@ public bool IsLocationChanged
///
/// Private field of property.
///
- public bool _isDefaultLocation;
+ private bool _isDefaultLocation;
///
/// Indicates whether the current location is the default settings folder location.
From 2bcae6e5e35b028dac6a8460743dbbad35660bce Mon Sep 17 00:00:00 2001
From: BornToBeRoot <16019165+BornToBeRoot@users.noreply.github.com>
Date: Wed, 18 Feb 2026 01:38:59 +0100
Subject: [PATCH 20/25] Update
Source/NETworkManager.Settings/SettingsManager.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
---
Source/NETworkManager.Settings/SettingsManager.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Source/NETworkManager.Settings/SettingsManager.cs b/Source/NETworkManager.Settings/SettingsManager.cs
index 523a70561c..302efe79a0 100644
--- a/Source/NETworkManager.Settings/SettingsManager.cs
+++ b/Source/NETworkManager.Settings/SettingsManager.cs
@@ -161,7 +161,7 @@ private static string ValidateSettingsFolderPath(string path, string pathSource,
return null;
}
- return fullPath.TrimEnd('\\');
+ return Path.TrimEndingDirectorySeparator(fullPath);
}
catch (ArgumentException ex)
{
From ae6fe1f2024a1f2792cacaf6b06e19f7a8486af8 Mon Sep 17 00:00:00 2001
From: BornToBeRoot <16019165+BornToBeRoot@users.noreply.github.com>
Date: Wed, 18 Feb 2026 22:37:53 +0100
Subject: [PATCH 21/25] Update
Source/NETworkManager.Settings/LocalSettingsManager.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
---
Source/NETworkManager.Settings/LocalSettingsManager.cs | 1 -
1 file changed, 1 deletion(-)
diff --git a/Source/NETworkManager.Settings/LocalSettingsManager.cs b/Source/NETworkManager.Settings/LocalSettingsManager.cs
index 011a1bae1d..e9822772a3 100644
--- a/Source/NETworkManager.Settings/LocalSettingsManager.cs
+++ b/Source/NETworkManager.Settings/LocalSettingsManager.cs
@@ -1,5 +1,4 @@
using log4net;
-using Microsoft.Xaml.Behaviors.Media;
using System;
using System.IO;
using System.Text.Json;
From 3dae961b0e5a34c5c29b829d69930cdb3ba8ea72 Mon Sep 17 00:00:00 2001
From: BornToBeRoot <16019165+BornToBeRoot@users.noreply.github.com>
Date: Wed, 18 Feb 2026 22:53:33 +0100
Subject: [PATCH 22/25] Fix: Handle LocalSettingsManager.Load() gracefully
---
.../LocalSettingsManager.cs | 41 ++++++++++++++-----
.../NETworkManager.Settings/PolicyManager.cs | 1 +
Source/NETworkManager/App.xaml.cs | 12 ++----
3 files changed, 34 insertions(+), 20 deletions(-)
diff --git a/Source/NETworkManager.Settings/LocalSettingsManager.cs b/Source/NETworkManager.Settings/LocalSettingsManager.cs
index e9822772a3..a1d49a776e 100644
--- a/Source/NETworkManager.Settings/LocalSettingsManager.cs
+++ b/Source/NETworkManager.Settings/LocalSettingsManager.cs
@@ -86,19 +86,38 @@ public static void Load()
if (File.Exists(filePath))
{
- Log.Info($"Loading local settings from: {filePath}");
-
- var jsonString = File.ReadAllText(filePath);
- Current = JsonSerializer.Deserialize(jsonString, JsonOptions);
-
- Log.Info("Local settings loaded successfully.");
-
- // Reset change tracking
- Current.SettingsChanged = false;
-
- return;
+ try
+ {
+ Log.Info($"Loading local settings from: {filePath}");
+
+ var jsonString = File.ReadAllText(filePath);
+
+ // Treat empty or JSON "null" as "no settings" instead of crashing
+ if (string.IsNullOrWhiteSpace(jsonString))
+ {
+ Log.Info("Local settings file is empty, initializing new local settings.");
+ }
+ else
+ {
+ Current = JsonSerializer.Deserialize(jsonString, JsonOptions);
+
+ Log.Info("Local settings loaded successfully.");
+
+ // Reset change tracking
+ Current.SettingsChanged = false;
+
+ return;
+ }
+ }
+ catch (Exception ex)
+ {
+ {
+ Log.Error($"Failed to load local settings from: {filePath}", ex);
+ }
+ }
}
+ // Initialize new settings if loading failed or file does not exist
Initialize();
}
diff --git a/Source/NETworkManager.Settings/PolicyManager.cs b/Source/NETworkManager.Settings/PolicyManager.cs
index fc946620bc..ddbdfd3d38 100644
--- a/Source/NETworkManager.Settings/PolicyManager.cs
+++ b/Source/NETworkManager.Settings/PolicyManager.cs
@@ -73,6 +73,7 @@ public static void Load()
if (string.IsNullOrWhiteSpace(jsonString))
{
Current = new PolicyInfo();
+
Log.Info("Config file is empty, no system-wide policies loaded.");
}
else
diff --git a/Source/NETworkManager/App.xaml.cs b/Source/NETworkManager/App.xaml.cs
index 1070bc951b..112da3063e 100644
--- a/Source/NETworkManager/App.xaml.cs
+++ b/Source/NETworkManager/App.xaml.cs
@@ -88,7 +88,7 @@ by BornToBeRoot
// Load (or initialize) local settings
LocalSettingsManager.Load();
-
+
// Load (or initialize) settings
try
{
@@ -97,18 +97,12 @@ by BornToBeRoot
else
SettingsManager.Load();
}
- catch (InvalidOperationException ex)
+ catch (Exception ex)
{
Log.Error("Could not load application settings!", ex);
HandleCorruptedSettingsFile();
- }
- catch (JsonException ex)
- {
- Log.Error("Could not load application settings! JSON file is corrupted or invalid.", ex);
-
- HandleCorruptedSettingsFile();
- }
+ }
// Upgrade settings if necessary
var settingsVersion = Version.Parse(SettingsManager.Current.Version);
From 85952da9fb7a80f08934c78cbf60ac66dcbda42f Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 18 Feb 2026 21:55:47 +0000
Subject: [PATCH 23/25] Fix exception handling for LocalSettingsManager and
path validation
Co-authored-by: BornToBeRoot <16019165+BornToBeRoot@users.noreply.github.com>
---
.../LocalSettingsManager.cs | 20 +++++++++++++------
.../SettingsManager.cs | 12 ++++++++++-
Source/NETworkManager/App.xaml.cs | 17 +++++++++++++++-
3 files changed, 41 insertions(+), 8 deletions(-)
diff --git a/Source/NETworkManager.Settings/LocalSettingsManager.cs b/Source/NETworkManager.Settings/LocalSettingsManager.cs
index a1d49a776e..0b6d651747 100644
--- a/Source/NETworkManager.Settings/LocalSettingsManager.cs
+++ b/Source/NETworkManager.Settings/LocalSettingsManager.cs
@@ -101,12 +101,20 @@ public static void Load()
{
Current = JsonSerializer.Deserialize(jsonString, JsonOptions);
- Log.Info("Local settings loaded successfully.");
-
- // Reset change tracking
- Current.SettingsChanged = false;
-
- return;
+ // Check if deserialization returned null (e.g., file contains "null")
+ if (Current == null)
+ {
+ Log.Warn("Local settings deserialized to null, initializing new local settings.");
+ }
+ else
+ {
+ Log.Info("Local settings loaded successfully.");
+
+ // Reset change tracking
+ Current.SettingsChanged = false;
+
+ return;
+ }
}
}
catch (Exception ex)
diff --git a/Source/NETworkManager.Settings/SettingsManager.cs b/Source/NETworkManager.Settings/SettingsManager.cs
index 302efe79a0..bf28e261df 100644
--- a/Source/NETworkManager.Settings/SettingsManager.cs
+++ b/Source/NETworkManager.Settings/SettingsManager.cs
@@ -151,7 +151,7 @@ private static string ValidateSettingsFolderPath(string path, string pathSource,
// Validate that the path doesn't contain invalid characters
try
{
- // This will throw ArgumentException, NotSupportedException, or SecurityException if the path is invalid
+ // This will throw ArgumentException, NotSupportedException, SecurityException, PathTooLongException, or IOException if the path is invalid
var fullPath = Path.GetFullPath(path);
// Check if the path is a directory (not a file)
@@ -178,6 +178,16 @@ private static string ValidateSettingsFolderPath(string path, string pathSource,
Log.Error($"Insufficient permissions to access {pathSource} SettingsFolderLocation: {path}. Falling back to {fallbackMessage}.", ex);
return null;
}
+ catch (PathTooLongException ex)
+ {
+ Log.Error($"{pathSource} SettingsFolderLocation path is too long: {path}. Falling back to {fallbackMessage}.", ex);
+ return null;
+ }
+ catch (IOException ex)
+ {
+ Log.Error($"{pathSource} SettingsFolderLocation caused an I/O error: {path}. Falling back to {fallbackMessage}.", ex);
+ return null;
+ }
}
///
diff --git a/Source/NETworkManager/App.xaml.cs b/Source/NETworkManager/App.xaml.cs
index 112da3063e..2180c63b1a 100644
--- a/Source/NETworkManager/App.xaml.cs
+++ b/Source/NETworkManager/App.xaml.cs
@@ -87,7 +87,22 @@ by BornToBeRoot
PolicyManager.Load();
// Load (or initialize) local settings
- LocalSettingsManager.Load();
+ try
+ {
+ LocalSettingsManager.Load();
+ }
+ catch (IOException ex)
+ {
+ Log.Error("Could not load local settings due to an I/O error! Using default local settings.", ex);
+ }
+ catch (UnauthorizedAccessException ex)
+ {
+ Log.Error("Could not load local settings due to insufficient permissions! Using default local settings.", ex);
+ }
+ catch (JsonException ex)
+ {
+ Log.Error("Could not load local settings! Local settings JSON is corrupted or invalid. Using default local settings.", ex);
+ }
// Load (or initialize) settings
try
From 66a6ca7429bc5b0cff34391da79e0ca868bbaac8 Mon Sep 17 00:00:00 2001
From: BornToBeRoot <16019165+BornToBeRoot@users.noreply.github.com>
Date: Wed, 18 Feb 2026 23:03:01 +0100
Subject: [PATCH 24/25] Fix: Minor improvements
---
.../LocalSettingsManager.cs | 28 ++++++-------------
Source/NETworkManager/App.xaml.cs | 17 +----------
2 files changed, 10 insertions(+), 35 deletions(-)
diff --git a/Source/NETworkManager.Settings/LocalSettingsManager.cs b/Source/NETworkManager.Settings/LocalSettingsManager.cs
index 0b6d651747..f03e5a7e45 100644
--- a/Source/NETworkManager.Settings/LocalSettingsManager.cs
+++ b/Source/NETworkManager.Settings/LocalSettingsManager.cs
@@ -99,29 +99,19 @@ public static void Load()
}
else
{
- Current = JsonSerializer.Deserialize(jsonString, JsonOptions);
-
- // Check if deserialization returned null (e.g., file contains "null")
- if (Current == null)
- {
- Log.Warn("Local settings deserialized to null, initializing new local settings.");
- }
- else
- {
- Log.Info("Local settings loaded successfully.");
-
- // Reset change tracking
- Current.SettingsChanged = false;
-
- return;
- }
+ Current = JsonSerializer.Deserialize(jsonString, JsonOptions) ?? new LocalSettingsInfo();
+
+ Log.Info("Local settings loaded successfully.");
+
+ // Reset change tracking
+ Current.SettingsChanged = false;
+
+ return;
}
}
catch (Exception ex)
{
- {
- Log.Error($"Failed to load local settings from: {filePath}", ex);
- }
+ Log.Error($"Failed to load local settings from: {filePath}", ex);
}
}
diff --git a/Source/NETworkManager/App.xaml.cs b/Source/NETworkManager/App.xaml.cs
index 2180c63b1a..112da3063e 100644
--- a/Source/NETworkManager/App.xaml.cs
+++ b/Source/NETworkManager/App.xaml.cs
@@ -87,22 +87,7 @@ by BornToBeRoot
PolicyManager.Load();
// Load (or initialize) local settings
- try
- {
- LocalSettingsManager.Load();
- }
- catch (IOException ex)
- {
- Log.Error("Could not load local settings due to an I/O error! Using default local settings.", ex);
- }
- catch (UnauthorizedAccessException ex)
- {
- Log.Error("Could not load local settings due to insufficient permissions! Using default local settings.", ex);
- }
- catch (JsonException ex)
- {
- Log.Error("Could not load local settings! Local settings JSON is corrupted or invalid. Using default local settings.", ex);
- }
+ LocalSettingsManager.Load();
// Load (or initialize) settings
try
From e344ae64382f34f2d5c53a10de5b62dc149c7766 Mon Sep 17 00:00:00 2001
From: BornToBeRoot <16019165+BornToBeRoot@users.noreply.github.com>
Date: Wed, 18 Feb 2026 23:24:17 +0100
Subject: [PATCH 25/25] Feature: Improve settings load
---
.../LocalSettingsManager.cs | 2 +-
.../SettingsManager.cs | 67 +++++++++++++------
Source/NETworkManager/App.xaml.cs | 42 ++----------
3 files changed, 52 insertions(+), 59 deletions(-)
diff --git a/Source/NETworkManager.Settings/LocalSettingsManager.cs b/Source/NETworkManager.Settings/LocalSettingsManager.cs
index f03e5a7e45..8c5c7747f4 100644
--- a/Source/NETworkManager.Settings/LocalSettingsManager.cs
+++ b/Source/NETworkManager.Settings/LocalSettingsManager.cs
@@ -115,7 +115,7 @@ public static void Load()
}
}
- // Initialize new settings if loading failed or file does not exist
+ // Initialize new local settings if file does not exist or loading failed
Initialize();
}
diff --git a/Source/NETworkManager.Settings/SettingsManager.cs b/Source/NETworkManager.Settings/SettingsManager.cs
index bf28e261df..8a289a632d 100644
--- a/Source/NETworkManager.Settings/SettingsManager.cs
+++ b/Source/NETworkManager.Settings/SettingsManager.cs
@@ -266,43 +266,68 @@ public static void Load()
// Check if JSON file exists
if (File.Exists(filePath))
{
- Log.Info($"Loading settings from: {filePath}");
+ try
+ {
+ Log.Info($"Loading settings from: {filePath}");
- Current = DeserializeFromFile(filePath);
+ Current = DeserializeFromFile(filePath);
- Log.Info("Settings loaded successfully.");
+ Log.Info("Settings loaded successfully.");
- // Reset change tracking
- Current.SettingsChanged = false;
+ // Reset change tracking
+ Current.SettingsChanged = false;
- return;
- }
+ return;
+ }
+ catch (Exception ex)
+ {
+ Log.Error($"Failed to load settings from: {filePath}", ex);
+
+ Backup(filePath,
+ GetSettingsFolderLocation(),
+ $"{TimestampHelper.GetTimestamp()}_corrupted_{Path.GetFileName(filePath)}");
+ ConfigurationManager.Current.ShowSettingsResetNoteOnStartup = true;
+ }
+ }
// Check if legacy XML file exists and migrate it
- if (File.Exists(legacyFilePath))
+ else if (File.Exists(legacyFilePath))
{
- Log.Info("Legacy XML settings file found. Migrating to JSON format...");
+ try
+ {
+ Log.Info("Legacy XML settings file found. Migrating to JSON format...");
- Current = DeserializeFromXmlFile(legacyFilePath);
+ Current = DeserializeFromXmlFile(legacyFilePath);
- Current.SettingsChanged = false;
+ Current.SettingsChanged = false;
- // Save in new JSON format
- Save();
+ // Save in new JSON format
+ Save();
- // Create a backup of the legacy XML file and delete the original
- Backup(legacyFilePath,
- GetSettingsBackupFolderLocation(),
- TimestampHelper.GetTimestampFilename(GetLegacySettingsFileName()));
+ // Create a backup of the legacy XML file and delete the original
+ Backup(legacyFilePath,
+ GetSettingsBackupFolderLocation(),
+ TimestampHelper.GetTimestampFilename(GetLegacySettingsFileName()));
- File.Delete(legacyFilePath);
+ File.Delete(legacyFilePath);
- Log.Info("Settings migration from XML to JSON completed successfully.");
+ Log.Info("Settings migration from XML to JSON completed successfully.");
- return;
+ return;
+ }
+ catch (Exception ex)
+ {
+ Log.Error($"Failed to load legacy settings from: {legacyFilePath}", ex);
+
+ Backup(legacyFilePath,
+ GetSettingsFolderLocation(),
+ $"{TimestampHelper.GetTimestamp()}_corrupted_{Path.GetFileName(legacyFilePath)}");
+
+ ConfigurationManager.Current.ShowSettingsResetNoteOnStartup = true;
+ }
}
- // Initialize the default settings if there is no settings file.
+ // Initialize new settings if file does not exist or loading failed
Initialize();
}
diff --git a/Source/NETworkManager/App.xaml.cs b/Source/NETworkManager/App.xaml.cs
index 112da3063e..74ac6812a3 100644
--- a/Source/NETworkManager/App.xaml.cs
+++ b/Source/NETworkManager/App.xaml.cs
@@ -1,8 +1,6 @@
using System;
using System.Diagnostics;
-using System.IO;
using System.Linq;
-using System.Text.Json;
using System.Threading;
using System.Windows;
using System.Windows.Threading;
@@ -88,21 +86,12 @@ by BornToBeRoot
// Load (or initialize) local settings
LocalSettingsManager.Load();
-
- // Load (or initialize) settings
- try
- {
- if (CommandLineManager.Current.ResetSettings)
- SettingsManager.Initialize();
- else
- SettingsManager.Load();
- }
- catch (Exception ex)
- {
- Log.Error("Could not load application settings!", ex);
- HandleCorruptedSettingsFile();
- }
+ // Load (or initialize) settings
+ if (CommandLineManager.Current.ResetSettings)
+ SettingsManager.Initialize();
+ else
+ SettingsManager.Load();
// Upgrade settings if necessary
var settingsVersion = Version.Parse(SettingsManager.Current.Version);
@@ -209,27 +198,6 @@ by BornToBeRoot
StartupUri = new Uri("MainWindow.xaml", UriKind.Relative);
}
- ///
- /// Handles a corrupted settings file by creating a backup and initializing default settings.
- ///
- private void HandleCorruptedSettingsFile()
- {
- // Create backup of corrupted file
- var destinationFile =
- $"{TimestampHelper.GetTimestamp()}_corrupted_" + SettingsManager.GetSettingsFileName();
-
- File.Copy(SettingsManager.GetSettingsFilePath(),
- Path.Combine(SettingsManager.GetSettingsFolderLocation(), destinationFile));
-
- Log.Info($"A backup of the corrupted settings file has been saved under {destinationFile}");
-
- // Initialize default application settings
- Log.Info("Initialize default application settings...");
-
- SettingsManager.Initialize();
- ConfigurationManager.Current.ShowSettingsResetNoteOnStartup = true;
- }
-
///
/// Handles the tick event of the dispatcher timer to trigger a background job and save data.
///