diff --git a/Source/NETworkManager.Localization/Resources/Strings.Designer.cs b/Source/NETworkManager.Localization/Resources/Strings.Designer.cs
index 40ef350d30..b431a282ac 100644
--- a/Source/NETworkManager.Localization/Resources/Strings.Designer.cs
+++ b/Source/NETworkManager.Localization/Resources/Strings.Designer.cs
@@ -1475,6 +1475,17 @@ public static string ChangeLocationSettingsMessage {
}
}
+ ///
+ /// Sucht eine lokalisierte Zeichenfolge, die The location is changed and the application is restarted afterwards.
+ ///
+ ///You can copy your profile files from "{0}" to "{1}" to migrate your previous profiles, if necessary. The application must be closed for this to prevent the profiles from being overwritten. ähnelt.
+ ///
+ public static string ChangeLocationProfilesMessage {
+ get {
+ return ResourceManager.GetString("ChangeLocationProfilesMessage", resourceCulture);
+ }
+ }
+
///
/// Sucht eine lokalisierte Zeichenfolge, die Changelog ähnelt.
///
@@ -8902,6 +8913,17 @@ public static string RestoreDefaultLocationSettingsMessage {
}
}
+ ///
+ /// Sucht eine lokalisierte Zeichenfolge, die The default path is restored and the application is restarted afterwards.
+ ///
+ ///You can copy your profile files from "{0}" to "{1}" to migrate your previous profiles, if necessary. The application must be closed for this to prevent the profiles from being overwritten. ähnelt.
+ ///
+ public static string RestoreDefaultLocationProfilesMessage {
+ get {
+ return ResourceManager.GetString("RestoreDefaultLocationProfilesMessage", resourceCulture);
+ }
+ }
+
///
/// Sucht eine lokalisierte Zeichenfolge, die Restore defaults ähnelt.
///
diff --git a/Source/NETworkManager.Localization/Resources/Strings.resx b/Source/NETworkManager.Localization/Resources/Strings.resx
index ad2eb07c93..550f519f38 100644
--- a/Source/NETworkManager.Localization/Resources/Strings.resx
+++ b/Source/NETworkManager.Localization/Resources/Strings.resx
@@ -3988,4 +3988,14 @@ You can copy the “settings.json” file from "{0}" to "{1}" to migrate your pr
Enter a valid folder path!
+
+ The location is changed and the application is restarted afterwards.
+
+You can copy your profile files from “{0}” to “{1}” to migrate your previous profiles, if necessary. The application must be closed for this to prevent the profiles from being overwritten.
+
+
+ The default path is restored and the application is restarted afterwards.
+
+You can copy your profile files from “{0}” to “{1}” to migrate your previous profiles, if necessary. The application must be closed for this to prevent the profiles from being overwritten.
+
\ No newline at end of file
diff --git a/Source/NETworkManager.Profiles/ProfileManager.cs b/Source/NETworkManager.Profiles/ProfileManager.cs
index bbb62fa382..6978c51d45 100644
--- a/Source/NETworkManager.Profiles/ProfileManager.cs
+++ b/Source/NETworkManager.Profiles/ProfileManager.cs
@@ -197,14 +197,121 @@ private static void ProfilesUpdated(bool profilesChanged = true)
///
/// Method to get the path of the profiles folder.
+ /// Priority: 1. Policy override, 2. Custom user path (from SettingsInfo), 3. Portable/default.
///
/// Path to the profiles folder.
public static string GetProfilesFolderLocation()
{
- return ConfigurationManager.Current.IsPortable
- ? Path.Combine(AssemblyManager.Current.Location, ProfilesFolderName)
- : Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
- AssemblyManager.Current.Name, ProfilesFolderName);
+ // 1. Policy override takes precedence (for IT administrators)
+ if (!string.IsNullOrWhiteSpace(PolicyManager.Current?.Profiles_FolderLocation))
+ {
+ var validatedPath = ValidateProfilesFolderPath(
+ PolicyManager.Current.Profiles_FolderLocation,
+ "Policy-provided",
+ "next priority");
+
+ if (validatedPath != null)
+ return validatedPath;
+ }
+
+ // 2. Custom user-configured path (not available in portable mode)
+ if (!ConfigurationManager.Current.IsPortable &&
+ !string.IsNullOrWhiteSpace(SettingsManager.Current?.Profiles_CustomProfilesFolderLocation))
+ {
+ var validatedPath = ValidateProfilesFolderPath(
+ SettingsManager.Current.Profiles_CustomProfilesFolderLocation,
+ "Custom",
+ "default location");
+
+ if (validatedPath != null)
+ return validatedPath;
+ }
+
+ // 3. Fall back to portable or default location
+ if (ConfigurationManager.Current.IsPortable)
+ return GetPortableProfilesFolderLocation();
+ else
+ return GetDefaultProfilesFolderLocation();
+ }
+
+ ///
+ /// Method to get the default profiles folder location in the user's Documents directory.
+ ///
+ /// Path to the default profiles folder location.
+ public static string GetDefaultProfilesFolderLocation()
+ {
+ return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
+ AssemblyManager.Current.Name, ProfilesFolderName);
+ }
+
+ ///
+ /// Method to get the portable profiles folder location (in the same directory as the application).
+ ///
+ /// Path to the portable profiles folder location.
+ public static string GetPortableProfilesFolderLocation()
+ {
+ return Path.Combine(AssemblyManager.Current.Location, ProfilesFolderName);
+ }
+
+ ///
+ /// Validates a profiles folder path for correctness and accessibility.
+ ///
+ /// The path to validate.
+ /// Description of the path source for logging (e.g., "Policy-provided", "Custom").
+ /// Message describing what happens on validation failure (e.g., "next priority", "default location").
+ /// The validated full path if valid; otherwise, null.
+ private static string ValidateProfilesFolderPath(string path, string pathSource, string fallbackMessage)
+ {
+ // Expand environment variables first (e.g. %userprofile%\profiles -> C:\Users\...\profiles)
+ path = Environment.ExpandEnvironmentVariables(path);
+
+ // Validate that the path is rooted (absolute)
+ if (!Path.IsPathRooted(path))
+ {
+ Log.Error($"{pathSource} Profiles_FolderLocation is not an absolute path: {path}. Falling back to {fallbackMessage}.");
+ return null;
+ }
+
+ // Validate that the path doesn't contain invalid characters
+ try
+ {
+ // 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)
+ if (File.Exists(fullPath))
+ {
+ Log.Error($"{pathSource} Profiles_FolderLocation is a file, not a directory: {path}. Falling back to {fallbackMessage}.");
+ return null;
+ }
+
+ return Path.TrimEndingDirectorySeparator(fullPath);
+ }
+ catch (ArgumentException ex)
+ {
+ Log.Error($"{pathSource} Profiles_FolderLocation contains invalid characters: {path}. Falling back to {fallbackMessage}.", ex);
+ return null;
+ }
+ catch (NotSupportedException ex)
+ {
+ Log.Error($"{pathSource} Profiles_FolderLocation format is not supported: {path}. Falling back to {fallbackMessage}.", ex);
+ return null;
+ }
+ catch (SecurityException ex)
+ {
+ Log.Error($"Insufficient permissions to access {pathSource} Profiles_FolderLocation: {path}. Falling back to {fallbackMessage}.", ex);
+ return null;
+ }
+ catch (PathTooLongException ex)
+ {
+ Log.Error($"{pathSource} Profiles_FolderLocation path is too long: {path}. Falling back to {fallbackMessage}.", ex);
+ return null;
+ }
+ catch (IOException ex)
+ {
+ Log.Error($"{pathSource} Profiles_FolderLocation caused an I/O error: {path}. Falling back to {fallbackMessage}.", ex);
+ return null;
+ }
}
///
diff --git a/Source/NETworkManager.Settings/LocalSettingsInfo.cs b/Source/NETworkManager.Settings/LocalSettingsInfo.cs
index 6c7d1a692f..b3388d396e 100644
--- a/Source/NETworkManager.Settings/LocalSettingsInfo.cs
+++ b/Source/NETworkManager.Settings/LocalSettingsInfo.cs
@@ -34,23 +34,23 @@ private void OnPropertyChanged([CallerMemberName] string propertyName = null)
[JsonIgnore] public bool SettingsChanged { get; set; }
///
- /// Private field for the property."
+ /// Private field for the property."
///
- private string _settingsFolderLocation;
+ private string _settings_FolderLocation;
///
/// Location of the folder where the local settings file is stored.
/// This can be changed by the user to move the settings file to a different location.
///
- public string SettingsFolderLocation
+ public string Settings_FolderLocation
{
- get => _settingsFolderLocation;
+ get => _settings_FolderLocation;
set
{
- if (_settingsFolderLocation == value)
+ if (_settings_FolderLocation == value)
return;
- _settingsFolderLocation = value;
+ _settings_FolderLocation = value;
OnPropertyChanged();
}
}
diff --git a/Source/NETworkManager.Settings/PolicyInfo.cs b/Source/NETworkManager.Settings/PolicyInfo.cs
index 2f17ee8abf..55d6767084 100644
--- a/Source/NETworkManager.Settings/PolicyInfo.cs
+++ b/Source/NETworkManager.Settings/PolicyInfo.cs
@@ -11,6 +11,9 @@ public class PolicyInfo
[JsonPropertyName("Update_CheckForUpdatesAtStartup")]
public bool? Update_CheckForUpdatesAtStartup { get; set; }
- [JsonPropertyName("SettingsFolderLocation")]
- public string? SettingsFolderLocation { get; set; }
+ [JsonPropertyName("Settings_FolderLocation")]
+ public string? Settings_FolderLocation { get; set; }
+
+ [JsonPropertyName("Profiles_FolderLocation")]
+ public string? Profiles_FolderLocation { get; set; }
}
diff --git a/Source/NETworkManager.Settings/PolicyManager.cs b/Source/NETworkManager.Settings/PolicyManager.cs
index ddbdfd3d38..26063ac16b 100644
--- a/Source/NETworkManager.Settings/PolicyManager.cs
+++ b/Source/NETworkManager.Settings/PolicyManager.cs
@@ -84,7 +84,8 @@ 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"}");
+ Log.Info($"System-wide policy - Settings_FolderLocation: {Current.Settings_FolderLocation ?? "Not set"}");
+ Log.Info($"System-wide policy - Profiles_FolderLocation: {Current.Profiles_FolderLocation ?? "Not set"}");
}
}
catch (Exception ex)
diff --git a/Source/NETworkManager.Settings/SettingsInfo.cs b/Source/NETworkManager.Settings/SettingsInfo.cs
index 5e810c8ec3..0bbf9d31f1 100644
--- a/Source/NETworkManager.Settings/SettingsInfo.cs
+++ b/Source/NETworkManager.Settings/SettingsInfo.cs
@@ -622,6 +622,25 @@ public int Profiles_MaximumNumberOfBackups
}
}
+ private string _profiles_CustomProfilesFolderLocation;
+
+ ///
+ /// Custom profiles folder location set by the user.
+ /// When set, overrides the default profiles folder location.
+ ///
+ public string Profiles_CustomProfilesFolderLocation
+ {
+ get => _profiles_CustomProfilesFolderLocation;
+ set
+ {
+ if (value == _profiles_CustomProfilesFolderLocation)
+ return;
+
+ _profiles_CustomProfilesFolderLocation = value;
+ OnPropertyChanged();
+ }
+ }
+
// Settings
private bool _settings_IsDailyBackupEnabled = GlobalStaticConfiguration.Settings_IsDailyBackupEnabled;
diff --git a/Source/NETworkManager.Settings/SettingsManager.cs b/Source/NETworkManager.Settings/SettingsManager.cs
index 8a289a632d..6852016be9 100644
--- a/Source/NETworkManager.Settings/SettingsManager.cs
+++ b/Source/NETworkManager.Settings/SettingsManager.cs
@@ -79,10 +79,10 @@ public static class SettingsManager
public static string GetSettingsFolderLocation()
{
// 1. Policy override takes precedence (for IT administrators)
- if (!string.IsNullOrWhiteSpace(PolicyManager.Current?.SettingsFolderLocation))
+ if (!string.IsNullOrWhiteSpace(PolicyManager.Current?.Settings_FolderLocation))
{
var validatedPath = ValidateSettingsFolderPath(
- PolicyManager.Current.SettingsFolderLocation,
+ PolicyManager.Current.Settings_FolderLocation,
"Policy-provided",
"next priority");
@@ -92,10 +92,10 @@ public static string GetSettingsFolderLocation()
// 2. Custom user-configured path (not available in portable mode)
if (!ConfigurationManager.Current.IsPortable &&
- !string.IsNullOrWhiteSpace(LocalSettingsManager.Current?.SettingsFolderLocation))
+ !string.IsNullOrWhiteSpace(LocalSettingsManager.Current?.Settings_FolderLocation))
{
var validatedPath = ValidateSettingsFolderPath(
- LocalSettingsManager.Current.SettingsFolderLocation,
+ LocalSettingsManager.Current.Settings_FolderLocation,
"Custom",
"default location");
@@ -144,7 +144,7 @@ private static string ValidateSettingsFolderPath(string path, string pathSource,
// Validate that the path is rooted (absolute)
if (!Path.IsPathRooted(path))
{
- Log.Error($"{pathSource} SettingsFolderLocation is not an absolute path: {path}. Falling back to {fallbackMessage}.");
+ Log.Error($"{pathSource} Settings_FolderLocation is not an absolute path: {path}. Falling back to {fallbackMessage}.");
return null;
}
@@ -157,7 +157,7 @@ private static string ValidateSettingsFolderPath(string path, string pathSource,
// Check if the path is a directory (not a file)
if (File.Exists(fullPath))
{
- Log.Error($"{pathSource} SettingsFolderLocation is a file, not a directory: {path}. Falling back to {fallbackMessage}.");
+ Log.Error($"{pathSource} Settings_FolderLocation is a file, not a directory: {path}. Falling back to {fallbackMessage}.");
return null;
}
@@ -165,27 +165,27 @@ private static string ValidateSettingsFolderPath(string path, string pathSource,
}
catch (ArgumentException ex)
{
- Log.Error($"{pathSource} SettingsFolderLocation contains invalid characters: {path}. Falling back to {fallbackMessage}.", ex);
+ Log.Error($"{pathSource} Settings_FolderLocation contains invalid characters: {path}. Falling back to {fallbackMessage}.", ex);
return null;
}
catch (NotSupportedException ex)
{
- Log.Error($"{pathSource} SettingsFolderLocation format is not supported: {path}. Falling back to {fallbackMessage}.", ex);
+ Log.Error($"{pathSource} Settings_FolderLocation format is not supported: {path}. Falling back to {fallbackMessage}.", ex);
return null;
}
catch (SecurityException ex)
{
- Log.Error($"Insufficient permissions to access {pathSource} SettingsFolderLocation: {path}. Falling back to {fallbackMessage}.", ex);
+ Log.Error($"Insufficient permissions to access {pathSource} Settings_FolderLocation: {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);
+ Log.Error($"{pathSource} Settings_FolderLocation 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);
+ Log.Error($"{pathSource} Settings_FolderLocation caused an I/O error: {path}. Falling back to {fallbackMessage}.", ex);
return null;
}
}
diff --git a/Source/NETworkManager.Settings/config.json.example b/Source/NETworkManager.Settings/config.json.example
index 0a47ffa700..3747efaeaa 100644
--- a/Source/NETworkManager.Settings/config.json.example
+++ b/Source/NETworkManager.Settings/config.json.example
@@ -1,4 +1,5 @@
{
"Update_CheckForUpdatesAtStartup": false,
- "SettingsFolderLocation": "C:\\CustomPath\\NETworkManager\\Settings"
+ "Settings_FolderLocation": "C:\\CustomPath\\NETworkManager\\Settings",
+ "Profiles_FolderLocation": "C:\\CustomPath\\NETworkManager\\Profiles"
}
\ No newline at end of file
diff --git a/Source/NETworkManager/ViewModels/SettingsProfilesViewModel.cs b/Source/NETworkManager/ViewModels/SettingsProfilesViewModel.cs
index e2c58d980d..c9efb56184 100644
--- a/Source/NETworkManager/ViewModels/SettingsProfilesViewModel.cs
+++ b/Source/NETworkManager/ViewModels/SettingsProfilesViewModel.cs
@@ -7,6 +7,7 @@
using System;
using System.ComponentModel;
using System.Diagnostics;
+using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Threading.Tasks;
@@ -34,11 +35,55 @@ public string Location
if (value == _location)
return;
+ if (!_isLoading)
+ IsLocationChanged = !string.Equals(value, ProfileManager.GetProfilesFolderLocation(), StringComparison.OrdinalIgnoreCase);
+
_location = value;
OnPropertyChanged();
}
}
+ ///
+ /// Indicates whether the profiles location is managed by a system-wide policy.
+ ///
+ public bool IsLocationManagedByPolicy => !string.IsNullOrWhiteSpace(PolicyManager.Current?.Profiles_FolderLocation);
+
+ private bool _isLocationChanged;
+
+ ///
+ /// Gets or sets a value indicating whether the location has changed.
+ ///
+ public bool IsLocationChanged
+ {
+ get => _isLocationChanged;
+ set
+ {
+ if (value == _isLocationChanged)
+ return;
+
+ _isLocationChanged = value;
+ OnPropertyChanged();
+ }
+ }
+
+ private bool _isDefaultLocation;
+
+ ///
+ /// Indicates whether the current location is the default profiles folder location.
+ ///
+ public bool IsDefaultLocation
+ {
+ get => _isDefaultLocation;
+ set
+ {
+ if (value == _isDefaultLocation)
+ return;
+
+ _isDefaultLocation = value;
+ OnPropertyChanged();
+ }
+ }
+
private readonly ICollectionView _profileFiles;
public ICollectionView ProfileFiles
@@ -126,6 +171,7 @@ public SettingsProfilesViewModel()
private void LoadSettings()
{
Location = ProfileManager.GetProfilesFolderLocation();
+ IsDefaultLocation = string.Equals(Location, ProfileManager.GetDefaultProfilesFolderLocation(), StringComparison.OrdinalIgnoreCase);
IsDailyBackupEnabled = SettingsManager.Current.Profiles_IsDailyBackupEnabled;
MaximumNumberOfBackups = SettingsManager.Current.Profiles_MaximumNumberOfBackups;
}
@@ -141,6 +187,101 @@ private static void OpenLocationAction()
Process.Start("explorer.exe", ProfileManager.GetProfilesFolderLocation());
}
+ ///
+ /// 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.
+ ///
+ private void BrowseLocationFolderAction()
+ {
+ using var dialog = new System.Windows.Forms.FolderBrowserDialog();
+
+ if (Directory.Exists(Location))
+ dialog.SelectedPath = Location;
+
+ var dialogResult = dialog.ShowDialog();
+
+ if (dialogResult == System.Windows.Forms.DialogResult.OK)
+ Location = dialog.SelectedPath;
+ }
+
+ ///
+ /// Sets the location path based on the provided drag-and-drop input.
+ ///
+ /// The path to set as the location.
+ 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 profiles folder.
+ ///
+ /// A task that represents the asynchronous operation.
+ private async Task ChangeLocationAction()
+ {
+ var result = await DialogHelper.ShowConfirmationMessageAsync(Application.Current.MainWindow,
+ Strings.ChangeLocationQuestion,
+ string.Format(Strings.ChangeLocationProfilesMessage, ProfileManager.GetProfilesFolderLocation(), 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 in SettingsInfo
+ SettingsManager.Current.Profiles_CustomProfilesFolderLocation = Location;
+ SettingsManager.Save();
+
+ // Restart the application
+ (Application.Current.MainWindow as MainWindow)?.RestartApplication();
+ }
+
+ ///
+ /// Gets the command that restores the default location.
+ ///
+ public ICommand RestoreDefaultLocationCommand => new RelayCommand(_ => RestoreDefaultLocationActionAsync().ConfigureAwait(false));
+
+ ///
+ /// Restores the profiles folder location to the default path after obtaining user confirmation.
+ ///
+ /// A task that represents the asynchronous operation.
+ private async Task RestoreDefaultLocationActionAsync()
+ {
+ var result = await DialogHelper.ShowConfirmationMessageAsync(Application.Current.MainWindow,
+ Strings.RestoreDefaultLocationQuestion,
+ string.Format(Strings.RestoreDefaultLocationProfilesMessage, ProfileManager.GetProfilesFolderLocation(), ProfileManager.GetDefaultProfilesFolderLocation()),
+ ChildWindowIcon.Question,
+ Strings.Restore);
+
+ 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();
+
+ // Clear custom location to revert to default
+ SettingsManager.Current.Profiles_CustomProfilesFolderLocation = null;
+ SettingsManager.Save();
+
+ // Restart the application
+ (Application.Current.MainWindow as MainWindow)?.RestartApplication();
+ }
+
public ICommand AddProfileFileCommand => new RelayCommand(async _ => await AddProfileFileAction().ConfigureAwait(false));
private async Task AddProfileFileAction()
diff --git a/Source/NETworkManager/ViewModels/SettingsSettingsViewModel.cs b/Source/NETworkManager/ViewModels/SettingsSettingsViewModel.cs
index e14ee3639c..b726b0cab9 100644
--- a/Source/NETworkManager/ViewModels/SettingsSettingsViewModel.cs
+++ b/Source/NETworkManager/ViewModels/SettingsSettingsViewModel.cs
@@ -50,7 +50,7 @@ public string Location
///
/// Indicates whether the settings location is managed by a system-wide policy.
///
- public bool IsLocationManagedByPolicy => !string.IsNullOrWhiteSpace(PolicyManager.Current?.SettingsFolderLocation);
+ public bool IsLocationManagedByPolicy => !string.IsNullOrWhiteSpace(PolicyManager.Current?.Settings_FolderLocation);
///
/// Private field of property.
@@ -265,7 +265,7 @@ private async Task ChangeLocationAction()
SettingsManager.Save();
// Set new location
- LocalSettingsManager.Current.SettingsFolderLocation = Location;
+ LocalSettingsManager.Current.Settings_FolderLocation = Location;
LocalSettingsManager.Save();
// Restart the application
@@ -301,7 +301,7 @@ private async Task RestoreDefaultLocationActionAsync()
SettingsManager.Save();
// Clear custom location to revert to default
- LocalSettingsManager.Current.SettingsFolderLocation = null;
+ LocalSettingsManager.Current.Settings_FolderLocation = null;
LocalSettingsManager.Save();
// Restart the application
diff --git a/Source/NETworkManager/Views/SettingsProfilesView.xaml b/Source/NETworkManager/Views/SettingsProfilesView.xaml
index 0989c4a24d..3a19703688 100644
--- a/Source/NETworkManager/Views/SettingsProfilesView.xaml
+++ b/Source/NETworkManager/Views/SettingsProfilesView.xaml
@@ -10,36 +10,178 @@
xmlns:viewModels="clr-namespace:NETworkManager.ViewModels"
xmlns:localization="clr-namespace:NETworkManager.Localization.Resources;assembly=NETworkManager.Localization"
xmlns:profiles="clr-namespace:NETworkManager.Profiles;assembly=NETworkManager.Profiles"
+ xmlns:validators="clr-namespace:NETworkManager.Validators;assembly=NETworkManager.Validators"
+ xmlns:settings="clr-namespace:NETworkManager.Settings;assembly=NETworkManager.Settings"
mc:Ignorable="d" d:DataContext="{d:DesignInstance viewModels:SettingsProfilesViewModel}"
Loaded="UserControl_Loaded">
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 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)
+ - Profiles folder location (see [Profiles > Location](../settings/profiles.md#location) documentation for more information)
@@ -61,6 +62,10 @@ Release date: **xx.xx.2025**
- Settings folder location can now be changed by the user in the settings (see [Settings > Location](../settings/settings.md#location) documentation for more information). Additionally, it can be configured via a system-wide policy, allowing administrators to enforce a specific location for all users. [#3324](https://github.com/BornToBeRoot/NETworkManager/pull/3324)
+**Profiles**
+
+- Profiles folder location can now be changed by the user in the settings (see [Profiles > Location](../settings/profiles.md#location) documentation for more information). Additionally, it can be configured via a system-wide policy, allowing administrators to enforce a specific location for all users.
+
**Update**
- The update check at startup can now be configured via a system-wide policy, allowing administrators to control whether the application checks for updates (see [Update > Check for updates at startup](../settings/update.md#check-for-updates-at-startup) documentation for more information). [#3313](https://github.com/BornToBeRoot/NETworkManager/pull/3313)
diff --git a/Website/docs/settings/profiles.md b/Website/docs/settings/profiles.md
index 186924aa4b..bee88adbda 100644
--- a/Website/docs/settings/profiles.md
+++ b/Website/docs/settings/profiles.md
@@ -17,6 +17,30 @@ Folder where the application profiles are stored.
| Setup / Archiv | `%UserProfile%\Documents\NETworkManager\Profiles` |
| Portable | `\Profiles` |
+
+System-Wide Policy
+
+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:** `Profiles_FolderLocation`
+
+**Values:**
+
+- Absolute path (e.g., `C:\\Path\\To\\Profiles`)
+- Path with environment variables (e.g., `%UserProfile%\\NETworkManager\\Profiles`)
+- UNC path (e.g., `\\\\server\\share$\\NETworkManager\\Profiles`)
+- Omit the property to allow the default location logic to apply (portable vs. non-portable)
+
+**Example:**
+
+```json
+{
+ "Profiles_FolderLocation": "%UserProfile%\\NETworkManager\\Profiles"
+}
+```
+
+
+
:::note
**Recommendation**
diff --git a/Website/docs/settings/settings.md b/Website/docs/settings/settings.md
index 4164bf37b8..8ed1f795de 100644
--- a/Website/docs/settings/settings.md
+++ b/Website/docs/settings/settings.md
@@ -22,7 +22,7 @@ Folder where the application settings are stored.
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`
+**Policy Property:** `Settings_FolderLocation`
**Values:**
@@ -35,7 +35,7 @@ This setting can be controlled by administrators using a system-wide policy. See
```json
{
- "SettingsFolderLocation": "%UserProfile%\\NETworkManager\\Settings"
+ "Settings_FolderLocation": "%UserProfile%\\NETworkManager\\Settings"
}
```
diff --git a/Website/docs/system-wide-policies.md b/Website/docs/system-wide-policies.md
index 1756d5755a..103b1a8302 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:\\CustomPath\\NETworkManager\\Settings"
+ "Settings_FolderLocation": "C:\\CustomPath\\NETworkManager\\Settings"
}
```