diff --git a/Source/NETworkManager.Localization/Resources/Strings.Designer.cs b/Source/NETworkManager.Localization/Resources/Strings.Designer.cs
index 45583acc72..bd5ba1fb2c 100644
--- a/Source/NETworkManager.Localization/Resources/Strings.Designer.cs
+++ b/Source/NETworkManager.Localization/Resources/Strings.Designer.cs
@@ -4687,6 +4687,15 @@ public static string FlushDNSCache {
return ResourceManager.GetString("FlushDNSCache", resourceCulture);
}
}
+
+ ///
+ /// Looks up a localized string similar to DNS cache flushed.
+ ///
+ public static string FlushDNSCacheSuccessfully {
+ get {
+ return ResourceManager.GetString("FlushDNSCacheSuccessfully", resourceCulture);
+ }
+ }
///
/// Looks up a localized string similar to Folder does not exists!.
@@ -5841,6 +5850,78 @@ public static string IPv4Address {
return ResourceManager.GetString("IPv4Address", resourceCulture);
}
}
+
+ ///
+ /// Looks up a localized string similar to IPv4 address added.
+ ///
+ public static string IPv4AddressAddedSuccessfully {
+ get {
+ return ResourceManager.GetString("IPv4AddressAddedSuccessfully", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to IPv4 address released and renewed.
+ ///
+ public static string IPv4AddressReleasedAndRenewedSuccessfully {
+ get {
+ return ResourceManager.GetString("IPv4AddressReleasedAndRenewedSuccessfully", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to IPv4 address released.
+ ///
+ public static string IPv4AddressReleasedSuccessfully {
+ get {
+ return ResourceManager.GetString("IPv4AddressReleasedSuccessfully", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to IPv4 address renewed.
+ ///
+ public static string IPv4AddressRenewedSuccessfully {
+ get {
+ return ResourceManager.GetString("IPv4AddressRenewedSuccessfully", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to IPv6 address released and renewed.
+ ///
+ public static string IPv6AddressReleasedAndRenewedSuccessfully {
+ get {
+ return ResourceManager.GetString("IPv6AddressReleasedAndRenewedSuccessfully", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to IPv6 address released.
+ ///
+ public static string IPv6AddressReleasedSuccessfully {
+ get {
+ return ResourceManager.GetString("IPv6AddressReleasedSuccessfully", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to IPv6 address renewed.
+ ///
+ public static string IPv6AddressRenewedSuccessfully {
+ get {
+ return ResourceManager.GetString("IPv6AddressRenewedSuccessfully", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to IPv4 address removed.
+ ///
+ public static string IPv4AddressRemovedSuccessfully {
+ get {
+ return ResourceManager.GetString("IPv4AddressRemovedSuccessfully", resourceCulture);
+ }
+ }
///
/// Looks up a localized string similar to IPv4-Default-Gateway.
@@ -7038,7 +7119,25 @@ public static string NetworkInterface {
return ResourceManager.GetString("NetworkInterface", resourceCulture);
}
}
-
+
+ ///
+ /// Looks up a localized string similar to Configuration applied.
+ ///
+ public static string NetworkInterfaceConfigurationAppliedSuccessfully {
+ get {
+ return ResourceManager.GetString("NetworkInterfaceConfigurationAppliedSuccessfully", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Configuring the network interface requires elevated rights!.
+ ///
+ public static string NetworkInterfaceConfigureAdminMessage {
+ get {
+ return ResourceManager.GetString("NetworkInterfaceConfigureAdminMessage", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Network kind.
///
diff --git a/Source/NETworkManager.Localization/Resources/Strings.resx b/Source/NETworkManager.Localization/Resources/Strings.resx
index 4c1ea12002..e56b832433 100644
--- a/Source/NETworkManager.Localization/Resources/Strings.resx
+++ b/Source/NETworkManager.Localization/Resources/Strings.resx
@@ -309,6 +309,12 @@
Network Interface
+
+ Configuration applied
+
+
+ Configuring the network interface requires elevated rights!
+
New tab
@@ -513,6 +519,30 @@
IPv4 address
+
+ IPv4 address added
+
+
+ IPv4 address removed
+
+
+ IPv4 address released and renewed
+
+
+ IPv4 address released
+
+
+ IPv4 address renewed
+
+
+ IPv6 address released and renewed
+
+
+ IPv6 address released
+
+
+ IPv6 address renewed
+
IPv4-Default-Gateway
@@ -1294,6 +1324,9 @@ Profile files are not affected!
Flush DNS cache
+
+ DNS cache flushed
+
Decrypt and load your credentials to select them.
diff --git a/Source/NETworkManager.Models/Network/NetworkInterface.cs b/Source/NETworkManager.Models/Network/NetworkInterface.cs
index bca63e1205..ff8905bb83 100644
--- a/Source/NETworkManager.Models/Network/NetworkInterface.cs
+++ b/Source/NETworkManager.Models/Network/NetworkInterface.cs
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
-using System.ComponentModel;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
@@ -230,9 +229,7 @@ public static List GetNetworkInterfaces()
DNSAutoconfigurationEnabled = dnsAutoconfigurationEnabled,
DNSSuffix = ipProperties.DnsSuffix,
DNSServer = [.. ipProperties.DnsAddresses],
- Profile = profileByAlias.TryGetValue(networkInterface.Name, out var profile)
- ? profile
- : NetworkProfile.NotConfigured
+ Profile = profileByAlias.GetValueOrDefault(networkInterface.Name, NetworkProfile.NotConfigured)
});
}
@@ -312,48 +309,52 @@ public static IPAddress DetectLocalIPAddressFromNetworkInterface(AddressFamily a
{
// Filter operational network interfaces
var networkInterfaces = GetNetworkInterfaces()
- .Where(x => x.IsOperational);
+ .Where(x => x.IsOperational)
+ .ToList();
var candidates = new List();
- // IPv4
- if (addressFamily == AddressFamily.InterNetwork)
+ switch (addressFamily)
{
- foreach (var networkInterface in networkInterfaces)
- {
- foreach (var ipAddress in networkInterface.IPv4Address)
- candidates.Add(ipAddress.Item1);
- }
-
- // Prefer non-link-local addresses
- var nonLinkLocal = candidates.Where(x =>
+ // IPv4
+ case AddressFamily.InterNetwork:
{
- var bytes = x.GetAddressBytes();
+ foreach (var networkInterface in networkInterfaces)
+ {
+ foreach (var ipAddress in networkInterface.IPv4Address)
+ candidates.Add(ipAddress.Item1);
+ }
- return !(bytes[0] == 169 && bytes[1] == 254);
- });
+ // Prefer non-link-local addresses
+ var nonLinkLocal = candidates.FirstOrDefault(x =>
+ {
+ var bytes = x.GetAddressBytes();
- // Return first non-link-local or first candidate if none found (might be null - no addresses at all)
- return nonLinkLocal.Any() ? nonLinkLocal.First() : candidates.FirstOrDefault();
- }
+ return !(bytes[0] == 169 && bytes[1] == 254);
+ });
- // IPv6
- if (addressFamily == AddressFamily.InterNetworkV6)
- {
- // First try to get global or unique local addresses
- foreach (var networkInterface in networkInterfaces)
- candidates.AddRange(networkInterface.IPv6Address);
+ // Return first non-link-local or first candidate if none found (might be null - no addresses at all)
+ return nonLinkLocal ?? candidates.FirstOrDefault();
+ }
+ // IPv6
+ case AddressFamily.InterNetworkV6:
+ {
+ // First try to get global or unique local addresses
+ foreach (var networkInterface in networkInterfaces)
+ candidates.AddRange(networkInterface.IPv6Address);
- // Return first candidate if any found
- if (candidates.Count != 0)
- return candidates.First();
+ // Return first candidate if any found
+ if (candidates.Count != 0)
+ return candidates.First();
- // Fallback to link-local addresses
- var firstWithLinkLocal = networkInterfaces
- .FirstOrDefault(ni => ni.IPv6AddressLinkLocal.Length != 0);
+ // Fallback to link-local addresses
+ var firstWithLinkLocal = networkInterfaces
+ .FirstOrDefault(ni => ni.IPv6AddressLinkLocal.Length != 0);
- if (firstWithLinkLocal != null)
- return firstWithLinkLocal.IPv6AddressLinkLocal.First();
+ if (firstWithLinkLocal != null)
+ return firstWithLinkLocal.IPv6AddressLinkLocal.First();
+ break;
+ }
}
return null;
@@ -384,17 +385,13 @@ private static IPAddress DetectGatewayFromLocalIPAddress(IPAddress localIPAddres
{
foreach (var networkInterface in GetNetworkInterfaces())
{
- // IPv4
- if (localIPAddress.AddressFamily == AddressFamily.InterNetwork)
+ switch (localIPAddress.AddressFamily)
{
- if (networkInterface.IPv4Address.Any(x => x.Item1.Equals(localIPAddress)))
+ // IPv4
+ case AddressFamily.InterNetwork when networkInterface.IPv4Address.Any(x => x.Item1.Equals(localIPAddress)):
return networkInterface.IPv4Gateway.FirstOrDefault();
- }
-
- // IPv6
- if (localIPAddress.AddressFamily == AddressFamily.InterNetworkV6)
- {
- if (networkInterface.IPv6Address.Contains(localIPAddress))
+ // IPv6
+ case AddressFamily.InterNetworkV6 when networkInterface.IPv6Address.Contains(localIPAddress):
return networkInterface.IPv6Gateway.FirstOrDefault();
}
}
@@ -407,7 +404,7 @@ private static IPAddress DetectGatewayFromLocalIPAddress(IPAddress localIPAddres
///
/// The configuration settings to apply to the network interface. Cannot be null.
/// A task that represents the asynchronous operation.
- public Task ConfigureNetworkInterfaceAsync(NetworkInterfaceConfig config)
+ public static Task ConfigureNetworkInterfaceAsync(NetworkInterfaceConfig config)
{
return Task.Run(() => ConfigureNetworkInterface(config));
}
@@ -415,43 +412,34 @@ public Task ConfigureNetworkInterfaceAsync(NetworkInterfaceConfig config)
///
/// Configures the network interface according to the specified settings.
///
- /// This method applies the provided network configuration by executing system commands. If
- /// static IP or DNS settings are enabled in the configuration, the corresponding values are set; otherwise, DHCP is
- /// used. The method may prompt for elevated permissions depending on system policy.
+ /// Requires the application to be running with administrator privileges.
/// An object containing the configuration parameters for the network interface, including IP address, subnet mask,
/// gateway, and DNS server settings. Cannot be null.
- private void ConfigureNetworkInterface(NetworkInterfaceConfig config)
+ private static void ConfigureNetworkInterface(NetworkInterfaceConfig config)
{
+ var name = PowerShellHelper.EscapeSingleQuotes(config.Name);
+ var commands = new List();
+
// IP
- var command = $"netsh interface ipv4 set address name='{config.Name}'";
- command += config.EnableStaticIPAddress
- ? $" source=static address={config.IPAddress} mask={config.Subnetmask} gateway={config.Gateway};"
- : " source=dhcp;";
+ if (config.EnableStaticIPAddress)
+ commands.Add($"& netsh interface ipv4 set address name='{name}' source=static address={config.IPAddress} mask={config.Subnetmask} gateway={config.Gateway}");
+ else
+ commands.Add($"& netsh interface ipv4 set address name='{name}' source=dhcp");
// DNS
- command += $"netsh interface ipv4 set DNSservers name='{config.Name}'";
- command += config.EnableStaticDNS
- ? $" source=static address={config.PrimaryDNSServer} register=primary validate=no;"
- : " source=dhcp;";
- command += config.EnableStaticDNS && !string.IsNullOrEmpty(config.SecondaryDNSServer)
- ? $"netsh interface ipv4 add DNSservers name='{config.Name}' address={config.SecondaryDNSServer} index=2 validate=no;"
- : "";
-
- try
+ if (config.EnableStaticDNS)
{
- PowerShellHelper.ExecuteCommand(command, true);
+ commands.Add($"& netsh interface ipv4 set dnsservers name='{name}' source=static address={config.PrimaryDNSServer} register=primary validate=no");
+
+ if (!string.IsNullOrEmpty(config.SecondaryDNSServer))
+ commands.Add($"& netsh interface ipv4 add dnsservers name='{name}' address={config.SecondaryDNSServer} index=2 validate=no");
}
- catch (Win32Exception win32Ex)
+ else
{
- switch (win32Ex.NativeErrorCode)
- {
- case 1223:
- OnUserHasCanceled();
- break;
- default:
- throw;
- }
+ commands.Add($"& netsh interface ipv4 set dnsservers name='{name}' source=dhcp");
}
+
+ RunCommands(commands);
}
///
@@ -466,15 +454,12 @@ public static Task FlushDnsAsync()
}
///
- /// Clears the local DNS resolver cache on the system by executing the appropriate system command.
+ /// Clears the local DNS resolver cache on the system.
///
- /// This method requires administrative privileges to successfully flush the DNS cache. If the
- /// application does not have sufficient permissions, the operation may fail.
+ /// Requires the application to be running with administrator privileges.
private static void FlushDns()
{
- const string command = "ipconfig /flushdns;";
-
- PowerShellHelper.ExecuteCommand(command);
+ RunCommands(["& ipconfig /flushdns"], checkExitCode: true);
}
///
@@ -491,29 +476,27 @@ public static Task ReleaseRenewAsync(IPConfigReleaseRenewMode mode, string adapt
///
/// Releases and/or renews the IP configuration for the specified network adapter using the given mode.
///
- /// This method executes the appropriate 'ipconfig' commands based on the specified mode. The
- /// operation affects only the adapter identified by the provided name. Ensure that the caller has sufficient
- /// privileges to modify network settings.
- /// A value that specifies which IP configuration operation to perform. Determines whether to release, renew, or
- /// perform both actions for IPv4 and/or IPv6 addresses.
- /// The name of the network adapter to target for the release or renew operation. Cannot be null or empty.
+ /// Requires the application to be running with administrator privileges.
+ /// A value that specifies which IP configuration operation to perform.
+ /// The name of the network adapter to target. Cannot be null or empty.
private static void ReleaseRenew(IPConfigReleaseRenewMode mode, string adapterName)
{
- var command = string.Empty;
+ var name = PowerShellHelper.EscapeSingleQuotes(adapterName);
+ var commands = new List();
if (mode is IPConfigReleaseRenewMode.ReleaseRenew or IPConfigReleaseRenewMode.Release)
- command += $"ipconfig /release '{adapterName}';";
+ commands.Add($"& ipconfig /release '{name}'");
if (mode is IPConfigReleaseRenewMode.ReleaseRenew or IPConfigReleaseRenewMode.Renew)
- command += $"ipconfig /renew '{adapterName}';";
+ commands.Add($"& ipconfig /renew '{name}'");
if (mode is IPConfigReleaseRenewMode.ReleaseRenew6 or IPConfigReleaseRenewMode.Release6)
- command += $"ipconfig /release6 '{adapterName}';";
+ commands.Add($"& ipconfig /release6 '{name}'");
if (mode is IPConfigReleaseRenewMode.ReleaseRenew6 or IPConfigReleaseRenewMode.Renew6)
- command += $"ipconfig /renew6 '{adapterName}';";
+ commands.Add($"& ipconfig /renew6 '{name}'");
- PowerShellHelper.ExecuteCommand(command);
+ RunCommands(commands, checkExitCode: true);
}
///
@@ -529,21 +512,20 @@ public static Task AddIPAddressToNetworkInterfaceAsync(NetworkInterfaceConfig co
///
/// Adds an IP address to the specified network interface using the provided configuration.
///
- /// If DHCP/static IP coexistence is enabled in the configuration, the method enables this
- /// feature before adding the IP address. This method requires appropriate system permissions to modify network
- /// interface settings.
+ /// Requires the application to be running with administrator privileges.
/// The network interface configuration containing the interface name, IP address, subnet mask, and DHCP/static
/// coexistence settings. Cannot be null.
private static void AddIPAddressToNetworkInterface(NetworkInterfaceConfig config)
{
- var command = string.Empty;
+ var name = PowerShellHelper.EscapeSingleQuotes(config.Name);
+ var commands = new List();
if (config.EnableDhcpStaticIpCoexistence)
- command += $"netsh interface ipv4 set interface interface='{config.Name}' dhcpstaticipcoexistence=enabled;";
+ commands.Add($"& netsh interface ipv4 set interface interface='{name}' dhcpstaticipcoexistence=enabled");
- command += $"netsh interface ipv4 add address '{config.Name}' {config.IPAddress} {config.Subnetmask};";
+ commands.Add($"& netsh interface ipv4 add address '{name}' {config.IPAddress} {config.Subnetmask}");
- PowerShellHelper.ExecuteCommand(command, true);
+ RunCommands(commands);
}
///
@@ -559,30 +541,38 @@ public static Task RemoveIPAddressFromNetworkInterfaceAsync(NetworkInterfaceConf
///
/// Removes the specified IP address from the given network interface configuration.
///
- /// This method removes the IP address from the network interface using a system command. The
- /// operation requires appropriate system permissions and may fail if the interface or IP address does not
- /// exist.
+ /// Requires the application to be running with administrator privileges.
/// The network interface configuration containing the name of the interface and the IP address to remove. Cannot be
/// null.
private static void RemoveIPAddressFromNetworkInterface(NetworkInterfaceConfig config)
{
- var command = $"netsh interface ipv4 delete address '{config.Name}' {config.IPAddress};";
-
- PowerShellHelper.ExecuteCommand(command, true);
+ var name = PowerShellHelper.EscapeSingleQuotes(config.Name);
+ RunCommands([$"& netsh interface ipv4 delete address '{name}' {config.IPAddress}"]);
}
- #endregion
+ ///
+ /// Runs one or more native commands via a PowerShell runspace.
+ /// When is , a non-zero
+ /// $LASTEXITCODE is treated as an error via Write-Error.
+ /// Use for netsh, whose exit codes are unreliable
+ /// for idempotent operations (e.g. returns 1 when already on DHCP).
+ ///
+ private static void RunCommands(IEnumerable commands, bool checkExitCode = false)
+ {
+ string script;
- #region Events
+ if (checkExitCode)
+ script = string.Join(Environment.NewLine, commands.Select(cmd =>
+ $"{cmd}{Environment.NewLine}if ($LASTEXITCODE -ne 0) {{ Write-Error \"Command failed with exit code $LASTEXITCODE\" }}"));
+ else
+ script = string.Join(Environment.NewLine, commands);
- ///
- /// Occurs when the user cancels the current operation (e.g. UAC prompt).
- ///
- public event EventHandler UserHasCanceled;
+ using var ps = SMA.PowerShell.Create();
+ ps.AddScript(script);
+ ps.Invoke();
- private void OnUserHasCanceled()
- {
- UserHasCanceled?.Invoke(this, EventArgs.Empty);
+ if (checkExitCode && ps.HadErrors)
+ throw new Exception(string.Join("; ", ps.Streams.Error.Select(e => e.ToString())));
}
#endregion
diff --git a/Source/NETworkManager.Utilities/PowerShellHelper.cs b/Source/NETworkManager.Utilities/PowerShellHelper.cs
index dea4df89db..42296e9d90 100644
--- a/Source/NETworkManager.Utilities/PowerShellHelper.cs
+++ b/Source/NETworkManager.Utilities/PowerShellHelper.cs
@@ -1,90 +1,7 @@
-using System;
-using System.ComponentModel;
-using System.IO;
-using System.Diagnostics;
-
-namespace NETworkManager.Utilities;
+namespace NETworkManager.Utilities;
public static class PowerShellHelper
{
- ///
- /// Path to the PowerShell executable. Using "powershell.exe" allows the system to resolve it from the PATH,
- /// ensuring compatibility across different Windows versions and configurations.
- ///
- private const string Powershell = "powershell.exe";
-
- ///
- /// Base options for PowerShell execution:
- /// -NoProfile: Prevents loading the user's PowerShell profile, ensuring a clean environment.
- /// -NoLogo: Suppresses the PowerShell logo, providing a cleaner output.
- ///
- private const string BaseOpts = "-NoProfile -NoLogo";
-
- ///
- /// Execute a PowerShell command. Writes a temporary script file if the command is longer than Windows limits.
- ///
- /// Command to execute.
- ///
- /// Start PowerShell as an administrator. Error code 1223 is returned when the UAC dialog is canceled by
- /// the user.
- ///
- /// Window style of the PowerShell console (Default: Hidden)
- public static void ExecuteCommand(string command, bool asAdmin = false, ProcessWindowStyle windowStyle = ProcessWindowStyle.Hidden)
- {
- string scriptPath = null;
- var commandOpts = $" -Command {command}";
-
- // Handle Windows command line length limit of 32,767 characters.
- if (Powershell.Length + BaseOpts.Length + commandOpts.Length > 32767)
- {
- scriptPath = Path.Combine(Path.GetTempPath(), $"NETworkManager_{Guid.NewGuid()}.ps1");
-
- File.WriteAllText(scriptPath, command);
-
- commandOpts = $" -ExecutionPolicy Bypass -File \"{scriptPath}\"";
- }
-
- try
- {
- var info = new ProcessStartInfo
- {
- FileName = Powershell,
- Arguments = $"{BaseOpts}{commandOpts}",
- UseShellExecute = true,
- WindowStyle = windowStyle
- };
-
- if (asAdmin)
- info.Verb = "runas";
-
- using var process = new Process();
- process.StartInfo = info;
- process.Start();
- process.WaitForExit();
- }
- catch (Win32Exception e) when (asAdmin)
- {
- if (e.NativeErrorCode != 1223)
- throw;
-
- // Nothing to handle on UAC cancellation
- }
- finally
- {
- if (scriptPath != null)
- {
- try
- {
- File.Delete(scriptPath);
- }
- catch
- {
- // ignored
- }
- }
- }
- }
-
///
/// Escapes a string for safe embedding inside a PowerShell single-quoted string
/// by doubling any single-quote characters.
diff --git a/Source/NETworkManager/ViewModels/NetworkInterfaceViewModel.cs b/Source/NETworkManager/ViewModels/NetworkInterfaceViewModel.cs
index ec851aa94d..6d82ec6e0c 100644
--- a/Source/NETworkManager/ViewModels/NetworkInterfaceViewModel.cs
+++ b/Source/NETworkManager/ViewModels/NetworkInterfaceViewModel.cs
@@ -22,7 +22,6 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
-using System.Diagnostics;
using System.Linq;
using System.Net.NetworkInformation;
using System.Net.Sockets;
@@ -1031,17 +1030,7 @@ await DialogHelper.ShowMessageAsync(Application.Current.MainWindow, Strings.Erro
/// Gets the command to apply the network configuration.
///
public ICommand ApplyConfigurationCommand =>
- new RelayCommand(_ => ApplyConfigurationAction(), ApplyConfiguration_CanExecute);
-
- ///
- /// Determines whether the ApplyConfiguration command can execute.
- ///
- private bool ApplyConfiguration_CanExecute(object parameter)
- {
- return Application.Current.MainWindow != null &&
- !((MetroWindow)Application.Current.MainWindow).IsAnyDialogOpen &&
- !ConfigurationManager.Current.IsChildWindowOpen;
- }
+ new RelayCommand(_ => ApplyConfigurationAction(), ConfigureCommands_CanExecute);
///
/// Action to apply the network configuration.
@@ -1054,7 +1043,7 @@ private void ApplyConfigurationAction()
///
/// Gets the command to apply the profile configuration.
///
- public ICommand ApplyProfileCommand => new RelayCommand(_ => ApplyProfileAction());
+ public ICommand ApplyProfileCommand => new RelayCommand(_ => ApplyProfileAction(), ConfigureCommands_CanExecute);
private void ApplyProfileAction()
{
@@ -1189,6 +1178,29 @@ private bool AdditionalCommands_CanExecute(object parameter)
!((MetroWindow)Application.Current.MainWindow).IsAnyDialogOpen &&
!ConfigurationManager.Current.IsChildWindowOpen;
}
+
+ private bool ConfigureCommands_CanExecute(object parameter) => ConfigurationManager.Current.IsAdmin &&
+ Application.Current.MainWindow != null &&
+ !((MetroWindow)Application.Current.MainWindow).IsAnyDialogOpen &&
+ !ConfigurationManager.Current.IsChildWindowOpen;
+
+ ///
+ /// Gets the command to restart the application with administrator privileges.
+ ///
+ public ICommand RestartAsAdminCommand => new RelayCommand(parameter => { _ = RestartAsAdminAction(); });
+
+ private async Task RestartAsAdminAction()
+ {
+ try
+ {
+ (Application.Current.MainWindow as MainWindow)?.RestartApplication(true);
+ }
+ catch (Exception ex)
+ {
+ await DialogHelper.ShowMessageAsync(Application.Current.MainWindow, Strings.Error, ex.Message,
+ ChildWindowIcon.Error);
+ }
+ }
///
/// Gets the command to open network connections.
@@ -1221,7 +1233,7 @@ private void IPScannerAction()
///
/// Gets the command to flush DNS.
///
- public ICommand FlushDNSCommand => new RelayCommand(_ => FlushDNSAction(), AdditionalCommands_CanExecute);
+ public ICommand FlushDNSCommand => new RelayCommand(_ => FlushDNSAction(), ConfigureCommands_CanExecute);
private void FlushDNSAction()
{
@@ -1231,7 +1243,7 @@ private void FlushDNSAction()
///
/// Gets the command to release and renew IP address.
///
- public ICommand ReleaseRenewCommand => new RelayCommand(_ => ReleaseRenewAction(), AdditionalCommands_CanExecute);
+ public ICommand ReleaseRenewCommand => new RelayCommand(_ => ReleaseRenewAction(), ConfigureCommands_CanExecute);
private void ReleaseRenewAction()
{
@@ -1241,7 +1253,7 @@ private void ReleaseRenewAction()
///
/// Gets the command to release IP address.
///
- public ICommand ReleaseCommand => new RelayCommand(_ => ReleaseAction(), AdditionalCommands_CanExecute);
+ public ICommand ReleaseCommand => new RelayCommand(_ => ReleaseAction(), ConfigureCommands_CanExecute);
private void ReleaseAction()
{
@@ -1251,17 +1263,17 @@ private void ReleaseAction()
///
/// Gets the command to renew IP address.
///
- public ICommand RenewCommand => new RelayCommand(_ => RenewAction(), AdditionalCommands_CanExecute);
+ public ICommand RenewCommand => new RelayCommand(_ => RenewAction(), ConfigureCommands_CanExecute);
private void RenewAction()
{
- _ = ReleaseRenewAsync(IPConfigReleaseRenewMode.Renew6);
+ _ = ReleaseRenewAsync(IPConfigReleaseRenewMode.Renew);
}
///
/// Gets the command to release and renew IPv6 address.
///
- public ICommand ReleaseRenew6Command => new RelayCommand(_ => ReleaseRenew6Action(), AdditionalCommands_CanExecute);
+ public ICommand ReleaseRenew6Command => new RelayCommand(_ => ReleaseRenew6Action(), ConfigureCommands_CanExecute);
private void ReleaseRenew6Action()
{
@@ -1271,7 +1283,7 @@ private void ReleaseRenew6Action()
///
/// Gets the command to release IPv6 address.
///
- public ICommand Release6Command => new RelayCommand(_ => Release6Action(), AdditionalCommands_CanExecute);
+ public ICommand Release6Command => new RelayCommand(_ => Release6Action(), ConfigureCommands_CanExecute);
private void Release6Action()
{
@@ -1281,18 +1293,18 @@ private void Release6Action()
///
/// Gets the command to renew IPv6 address.
///
- public ICommand Renew6Command => new RelayCommand(_ => Renew6Action(), AdditionalCommands_CanExecute);
+ public ICommand Renew6Command => new RelayCommand(_ => Renew6Action(), ConfigureCommands_CanExecute);
private void Renew6Action()
{
- _ = ReleaseRenewAsync(IPConfigReleaseRenewMode.Renew);
+ _ = ReleaseRenewAsync(IPConfigReleaseRenewMode.Renew6);
}
///
/// Gets the command to add an IPv4 address.
///
public ICommand AddIPv4AddressCommand => new RelayCommand(parameter => { _ = AddIPv4AddressAction(); },
- AdditionalCommands_CanExecute);
+ ConfigureCommands_CanExecute);
private async Task AddIPv4AddressAction()
{
@@ -1323,7 +1335,7 @@ private async Task AddIPv4AddressAction()
/// Gets the command to remove an IPv4 address.
///
public ICommand RemoveIPv4AddressCommand => new RelayCommand(parameter => { _ = RemoveIPv4AddressAction(); },
- AdditionalCommands_CanExecute);
+ ConfigureCommands_CanExecute);
private async Task RemoveIPv4AddressAction()
{
@@ -1463,13 +1475,12 @@ private async Task ApplyConfiguration()
try
{
- var networkInterface = new NetworkInterface();
-
- networkInterface.UserHasCanceled += NetworkInterface_UserHasCanceled;
-
- await networkInterface.ConfigureNetworkInterfaceAsync(config);
+ await NetworkInterface.ConfigureNetworkInterfaceAsync(config);
ReloadNetworkInterfaces();
+
+ StatusMessage = Strings.NetworkInterfaceConfigurationAppliedSuccessfully;
+ IsStatusMessageDisplayed = true;
}
catch (Exception ex)
{
@@ -1524,13 +1535,12 @@ private async Task ApplyConfigurationFromProfile()
try
{
- var networkInterface = new NetworkInterface();
-
- networkInterface.UserHasCanceled += NetworkInterface_UserHasCanceled;
-
- await networkInterface.ConfigureNetworkInterfaceAsync(config);
+ await NetworkInterface.ConfigureNetworkInterfaceAsync(config);
ReloadNetworkInterfaces();
+
+ StatusMessage = Strings.NetworkInterfaceConfigurationAppliedSuccessfully;
+ IsStatusMessageDisplayed = true;
}
catch (Exception ex)
{
@@ -1561,20 +1571,56 @@ private async Task FlushDNSAsync()
IsConfigurationRunning = true;
IsStatusMessageDisplayed = false;
- await NetworkInterface.FlushDnsAsync();
+ try
+ {
+ await NetworkInterface.FlushDnsAsync();
- IsConfigurationRunning = false;
+ StatusMessage = Strings.FlushDNSCacheSuccessfully;
+ IsStatusMessageDisplayed = true;
+ }
+ catch (Exception ex)
+ {
+ StatusMessage = ex.Message;
+ IsStatusMessageDisplayed = true;
+ }
+ finally
+ {
+ IsConfigurationRunning = false;
+ }
}
private async Task ReleaseRenewAsync(IPConfigReleaseRenewMode releaseRenewMode)
{
IsConfigurationRunning = true;
+ IsStatusMessageDisplayed = false;
- await NetworkInterface.ReleaseRenewAsync(releaseRenewMode, SelectedNetworkInterface.Name);
+ try
+ {
+ await NetworkInterface.ReleaseRenewAsync(releaseRenewMode, SelectedNetworkInterface.Name);
- ReloadNetworkInterfaces();
+ ReloadNetworkInterfaces();
- IsConfigurationRunning = false;
+ StatusMessage = releaseRenewMode switch
+ {
+ IPConfigReleaseRenewMode.ReleaseRenew => Strings.IPv4AddressReleasedAndRenewedSuccessfully,
+ IPConfigReleaseRenewMode.Release => Strings.IPv4AddressReleasedSuccessfully,
+ IPConfigReleaseRenewMode.Renew => Strings.IPv4AddressRenewedSuccessfully,
+ IPConfigReleaseRenewMode.ReleaseRenew6 => Strings.IPv6AddressReleasedAndRenewedSuccessfully,
+ IPConfigReleaseRenewMode.Release6 => Strings.IPv6AddressReleasedSuccessfully,
+ IPConfigReleaseRenewMode.Renew6 => Strings.IPv6AddressRenewedSuccessfully,
+ _ => string.Empty
+ };
+ IsStatusMessageDisplayed = true;
+ }
+ catch (Exception ex)
+ {
+ StatusMessage = ex.Message;
+ IsStatusMessageDisplayed = true;
+ }
+ finally
+ {
+ IsConfigurationRunning = false;
+ }
}
private async Task AddIPv4Address(string ipAddress, string subnetmaskOrCidr)
@@ -1601,6 +1647,9 @@ private async Task AddIPv4Address(string ipAddress, string subnetmaskOrCidr)
await NetworkInterface.AddIPAddressToNetworkInterfaceAsync(config);
ReloadNetworkInterfaces();
+
+ StatusMessage = Strings.IPv4AddressAddedSuccessfully;
+ IsStatusMessageDisplayed = true;
}
catch (Exception ex)
{
@@ -1629,6 +1678,9 @@ private async Task RemoveIPv4Address(string ipAddress)
await NetworkInterface.RemoveIPAddressFromNetworkInterfaceAsync(config);
ReloadNetworkInterfaces();
+
+ StatusMessage = Strings.IPv4AddressRemovedSuccessfully;
+ IsStatusMessageDisplayed = true;
}
catch (Exception ex)
{
@@ -1981,11 +2033,5 @@ private void BandwidthMeter_UpdateSpeed(object sender, BandwidthMeterSpeedArgs e
UpdateBandwidthYAxis();
}
- private void NetworkInterface_UserHasCanceled(object sender, EventArgs e)
- {
- StatusMessage = Strings.CanceledByUserMessage;
- IsStatusMessageDisplayed = true;
- }
-
#endregion
}
\ No newline at end of file
diff --git a/Source/NETworkManager/Views/NetworkInterfaceView.xaml b/Source/NETworkManager/Views/NetworkInterfaceView.xaml
index 31e7d04cef..4e8fba4956 100644
--- a/Source/NETworkManager/Views/NetworkInterfaceView.xaml
+++ b/Source/NETworkManager/Views/NetworkInterfaceView.xaml
@@ -554,8 +554,8 @@
-
-