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..e44073a3dc 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; @@ -407,7 +406,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 +414,32 @@ 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;"; + commands.Add(config.EnableStaticIPAddress + ? $"& netsh interface ipv4 set address name='{name}' source=static address={config.IPAddress} mask={config.Subnetmask} gateway={config.Gateway}" + : $"& 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 lines = new List(); if (mode is IPConfigReleaseRenewMode.ReleaseRenew or IPConfigReleaseRenewMode.Release) - command += $"ipconfig /release '{adapterName}';"; + lines.Add($"& ipconfig /release '{name}'"); if (mode is IPConfigReleaseRenewMode.ReleaseRenew or IPConfigReleaseRenewMode.Renew) - command += $"ipconfig /renew '{adapterName}';"; + lines.Add($"& ipconfig /renew '{name}'"); if (mode is IPConfigReleaseRenewMode.ReleaseRenew6 or IPConfigReleaseRenewMode.Release6) - command += $"ipconfig /release6 '{adapterName}';"; + lines.Add($"& ipconfig /release6 '{name}'"); if (mode is IPConfigReleaseRenewMode.ReleaseRenew6 or IPConfigReleaseRenewMode.Renew6) - command += $"ipconfig /renew6 '{adapterName}';"; + lines.Add($"& ipconfig /renew6 '{name}'"); - PowerShellHelper.ExecuteCommand(command); + RunCommands(lines, 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..a5ee057f07 100644 --- a/Source/NETworkManager/ViewModels/NetworkInterfaceViewModel.cs +++ b/Source/NETworkManager/ViewModels/NetworkInterfaceViewModel.cs @@ -1036,12 +1036,7 @@ await DialogHelper.ShowMessageAsync(Application.Current.MainWindow, Strings.Erro /// /// 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; - } + private bool ApplyConfiguration_CanExecute(object parameter) => AdminCanExecute(); /// /// Action to apply the network configuration. @@ -1054,7 +1049,7 @@ private void ApplyConfigurationAction() /// /// Gets the command to apply the profile configuration. /// - public ICommand ApplyProfileCommand => new RelayCommand(_ => ApplyProfileAction()); + public ICommand ApplyProfileCommand => new RelayCommand(_ => ApplyProfileAction(), ApplyConfiguration_CanExecute); private void ApplyProfileAction() { @@ -1190,6 +1185,34 @@ private bool AdditionalCommands_CanExecute(object parameter) !ConfigurationManager.Current.IsChildWindowOpen; } + private bool AdminCanExecute() + { + return ConfigurationManager.Current.IsAdmin && + Application.Current.MainWindow != null && + !((MetroWindow)Application.Current.MainWindow).IsAnyDialogOpen && + !ConfigurationManager.Current.IsChildWindowOpen; + } + + private bool ConfigureCommands_CanExecute(object parameter) => AdminCanExecute(); + + /// + /// 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 +1244,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 +1254,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 +1264,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 +1274,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 +1294,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 +1304,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 +1346,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 +1486,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 +1546,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 +1582,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 +1658,9 @@ private async Task AddIPv4Address(string ipAddress, string subnetmaskOrCidr) await NetworkInterface.AddIPAddressToNetworkInterfaceAsync(config); ReloadNetworkInterfaces(); + + StatusMessage = Strings.IPv4AddressAddedSuccessfully; + IsStatusMessageDisplayed = true; } catch (Exception ex) { @@ -1629,6 +1689,9 @@ private async Task RemoveIPv4Address(string ipAddress) await NetworkInterface.RemoveIPAddressFromNetworkInterfaceAsync(config); ReloadNetworkInterfaces(); + + StatusMessage = Strings.IPv4AddressRemovedSuccessfully; + IsStatusMessageDisplayed = true; } catch (Exception ex) { @@ -1981,11 +2044,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 @@ - - -