diff --git a/Source/NETworkManager.Localization/Resources/StaticStrings.Designer.cs b/Source/NETworkManager.Localization/Resources/StaticStrings.Designer.cs index d678382622..d61caf3ba7 100644 --- a/Source/NETworkManager.Localization/Resources/StaticStrings.Designer.cs +++ b/Source/NETworkManager.Localization/Resources/StaticStrings.Designer.cs @@ -573,6 +573,15 @@ public static string ExampleSNMPUsername { } } + /// + /// Sucht eine lokalisierte Zeichenfolge, die IoT-Devices ähnelt. + /// + public static string ExampleSsid { + get { + return ResourceManager.GetString("ExampleSsid", resourceCulture); + } + } + /// /// Sucht eine lokalisierte Zeichenfolge, die example.com ähnelt. /// diff --git a/Source/NETworkManager.Localization/Resources/StaticStrings.resx b/Source/NETworkManager.Localization/Resources/StaticStrings.resx index edbac3b25c..8d28ce5035 100644 --- a/Source/NETworkManager.Localization/Resources/StaticStrings.resx +++ b/Source/NETworkManager.Localization/Resources/StaticStrings.resx @@ -333,4 +333,7 @@ server-01.example.com:3389 + + IoT-Devices + \ No newline at end of file diff --git a/Source/NETworkManager.Localization/Resources/Strings.Designer.cs b/Source/NETworkManager.Localization/Resources/Strings.Designer.cs index fc056d7ab8..14738e507d 100644 --- a/Source/NETworkManager.Localization/Resources/Strings.Designer.cs +++ b/Source/NETworkManager.Localization/Resources/Strings.Designer.cs @@ -1446,6 +1446,15 @@ public static string CheckForUpdatesAtStartup { } } + /// + /// Sucht eine lokalisierte Zeichenfolge, die Checking WPS... ähnelt. + /// + public static string CheckingWPSDots { + get { + return ResourceManager.GetString("CheckingWPSDots", resourceCulture); + } + } + /// /// Sucht eine lokalisierte Zeichenfolge, die Check is disabled! ähnelt. /// @@ -1707,6 +1716,33 @@ public static string ConnectAsDots { } } + /// + /// Sucht eine lokalisierte Zeichenfolge, die Connect automatically ähnelt. + /// + public static string ConnectAutomatically { + get { + return ResourceManager.GetString("ConnectAutomatically", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die Connect... ähnelt. + /// + public static string ConnectDots { + get { + return ResourceManager.GetString("ConnectDots", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die Connected ähnelt. + /// + public static string Connected { + get { + return ResourceManager.GetString("Connected", resourceCulture); + } + } + /// /// Sucht eine lokalisierte Zeichenfolge, die Connect external ähnelt. /// @@ -1725,6 +1761,15 @@ public static string ConnectingDots { } } + /// + /// Sucht eine lokalisierte Zeichenfolge, die Connecting to {0}... ähnelt. + /// + public static string ConnectingToXXX { + get { + return ResourceManager.GetString("ConnectingToXXX", resourceCulture); + } + } + /// /// Sucht eine lokalisierte Zeichenfolge, die Connection ähnelt. /// @@ -1779,6 +1824,15 @@ public static string ConnectTheNetworkCardToConfigureIt { } } + /// + /// Sucht eine lokalisierte Zeichenfolge, die Connect to {0} ähnelt. + /// + public static string ConnectToXXX { + get { + return ResourceManager.GetString("ConnectToXXX", resourceCulture); + } + } + /// /// Sucht eine lokalisierte Zeichenfolge, die Continue ähnelt. /// @@ -1842,6 +1896,15 @@ public static string CouldNotConnectToXXXMessage { } } + /// + /// Sucht eine lokalisierte Zeichenfolge, die Could not connect to {0} ({1})! ähnelt. + /// + public static string CouldNotConnectToXXXReasonXXX { + get { + return ResourceManager.GetString("CouldNotConnectToXXXReasonXXX", resourceCulture); + } + } + /// /// Sucht eine lokalisierte Zeichenfolge, die Could not detect gateway ip address! ähnelt. /// @@ -3284,6 +3347,15 @@ public static string ErrorMessage_NameIsAlreadyUsed { } } + /// + /// Sucht eine lokalisierte Zeichenfolge, die Error while scanning WiFi adapter "{0}" with error: "{1}" ähnelt. + /// + public static string ErrorWhileScanningWiFiAdapterXXXWithErrorXXX { + get { + return ResourceManager.GetString("ErrorWhileScanningWiFiAdapterXXXWithErrorXXX", resourceCulture); + } + } + /// /// Sucht eine lokalisierte Zeichenfolge, die Everything ähnelt. /// @@ -6069,6 +6141,15 @@ public static string PreferredProtocolWhenResolvingHostname { } } + /// + /// Sucht eine lokalisierte Zeichenfolge, die Pre-shared key ähnelt. + /// + public static string PreSharedKey { + get { + return ResourceManager.GetString("PreSharedKey", resourceCulture); + } + } + /// /// Sucht eine lokalisierte Zeichenfolge, die Preview ähnelt. /// @@ -8679,6 +8760,15 @@ public static string Success { } } + /// + /// Sucht eine lokalisierte Zeichenfolge, die Successfully connected to {0}! ähnelt. + /// + public static string SuccessfullyConnectedToXXX { + get { + return ResourceManager.GetString("SuccessfullyConnectedToXXX", resourceCulture); + } + } + /// /// Sucht eine lokalisierte Zeichenfolge, die Synchronize all EC2 instances from AWS ähnelt. /// @@ -9842,6 +9932,69 @@ public static string WiFi { } } + /// + /// Sucht eine lokalisierte Zeichenfolge, die Access to the network has been revoked ähnelt. + /// + public static string WiFiConnectionStatus_AccessRevoked { + get { + return ResourceManager.GetString("WiFiConnectionStatus_AccessRevoked", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die Invalid credentials ähnelt. + /// + public static string WiFiConnectionStatus_InvalidCredential { + get { + return ResourceManager.GetString("WiFiConnectionStatus_InvalidCredential", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die Network not available ähnelt. + /// + public static string WiFiConnectionStatus_NetworkNotAvailable { + get { + return ResourceManager.GetString("WiFiConnectionStatus_NetworkNotAvailable", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die Successful ähnelt. + /// + public static string WiFiConnectionStatus_Success { + get { + return ResourceManager.GetString("WiFiConnectionStatus_Success", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die Connection attempt timed out ähnelt. + /// + public static string WiFiConnectionStatus_Timeout { + get { + return ResourceManager.GetString("WiFiConnectionStatus_Timeout", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die -/- ähnelt. + /// + public static string WiFiConnectionStatus_UnspecifiedFailure { + get { + return ResourceManager.GetString("WiFiConnectionStatus_UnspecifiedFailure", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die Authentication protocol is not supported! ähnelt. + /// + public static string WiFiConnectionStatus_UnsupportedAuthenticationProtocol { + get { + return ResourceManager.GetString("WiFiConnectionStatus_UnsupportedAuthenticationProtocol", resourceCulture); + } + } + /// /// Sucht eine lokalisierte Zeichenfolge, die Window ähnelt. /// @@ -9860,6 +10013,15 @@ public static string WindowsDNSSettings { } } + /// + /// Sucht eine lokalisierte Zeichenfolge, die WPS ähnelt. + /// + public static string WPS { + get { + return ResourceManager.GetString("WPS", resourceCulture); + } + } + /// /// Sucht eine lokalisierte Zeichenfolge, die Wrong password! ähnelt. /// @@ -9923,6 +10085,15 @@ public static string XXXDetectedAsLocalIPAddressMessage { } } + /// + /// Sucht eine lokalisierte Zeichenfolge, die {0} disconnected! ähnelt. + /// + public static string XXXDisconnected { + get { + return ResourceManager.GetString("XXXDisconnected", resourceCulture); + } + } + /// /// Sucht eine lokalisierte Zeichenfolge, die "{0}" is not reachable via ICMP! ähnelt. /// diff --git a/Source/NETworkManager.Localization/Resources/Strings.resx b/Source/NETworkManager.Localization/Resources/Strings.resx index 1143489891..818ecf37a3 100644 --- a/Source/NETworkManager.Localization/Resources/Strings.resx +++ b/Source/NETworkManager.Localization/Resources/Strings.resx @@ -3451,4 +3451,61 @@ Changes to this value will take effect after the application is restarted. Wheth The RD Gateway connection ended because periodic user authorization failed. Your computer or device didn't pass the Network Access Protection (NAP) requirements set by your network administrator. Contact your network administrator for assistance. + + Connected + + + Error while scanning WiFi adapter "{0}" with error: "{1}" + + + Connect... + + + {0} disconnected! + + + Connect to {0} + + + WPS + + + Connect automatically + + + Pre-shared key + + + Connecting to {0}... + + + Could not connect to {0} ({1})! + + + Successfully connected to {0}! + + + Access to the network has been revoked + + + Invalid credentials + + + Network not available + + + Successful + + + Connection attempt timed out + + + -/- + + + Authentication protocol is not supported! + + + Checking WPS... + \ No newline at end of file diff --git a/Source/NETworkManager.Localization/Translators/WiFiConnectionStatusTranslator.cs b/Source/NETworkManager.Localization/Translators/WiFiConnectionStatusTranslator.cs new file mode 100644 index 0000000000..80b01c90e3 --- /dev/null +++ b/Source/NETworkManager.Localization/Translators/WiFiConnectionStatusTranslator.cs @@ -0,0 +1,38 @@ +using NETworkManager.Models.PuTTY; +using NETworkManager.Utilities; +using Windows.Devices.WiFi; + +namespace NETworkManager.Localization.Translators; + +/// +/// Class to translate . +/// +public class WiFiConnectionStatusTranslator : SingletonBase, ILocalizationStringTranslator +{ + /// + /// Constant to identify the strings in the language files. + /// + private const string _identifier = "WiFiConnectionStatus_"; + + /// + /// Method to translate . + /// + /// . + /// Translated . + public string Translate(string value) + { + var translation = Resources.Strings.ResourceManager.GetString(_identifier + value, LocalizationManager.GetInstance().Culture); + + return string.IsNullOrEmpty(translation) ? value : translation; + } + + /// + /// Method to translate . + /// + /// . + /// Translated . + public string Translate(WiFiConnectionStatus status) + { + return Translate(status.ToString()); + } +} diff --git a/Source/NETworkManager.Models/Export/ExportManager.cs b/Source/NETworkManager.Models/Export/ExportManager.cs index 5a43cc2996..5550152de4 100644 --- a/Source/NETworkManager.Models/Export/ExportManager.cs +++ b/Source/NETworkManager.Models/Export/ExportManager.cs @@ -377,10 +377,10 @@ private static void CreateCSV(IEnumerable collection, string fi { var stringBuilder = new StringBuilder(); - stringBuilder.AppendLine($"{nameof(WiFiNetworkInfo.BSSID)},{nameof(WiFiNetworkInfo.SSID)},{nameof(WiFiNetworkInfo.ChannelCenterFrequencyInKilohertz)},{nameof(WiFiNetworkInfo.SignalBars)},{nameof(WiFiNetworkInfo.IsWiFiDirect)},{nameof(WiFiNetworkInfo.NetworkRssiInDecibelMilliwatts)},{nameof(WiFiNetworkInfo.PhyKind)},{nameof(WiFiNetworkInfo.NetworkKind)},{nameof(WiFiNetworkInfo.AuthenticationType)},{nameof(WiFiNetworkInfo.EncryptionType)},{nameof(WiFiNetworkInfo.BeaconInterval)}.{nameof(WiFiNetworkInfo.Uptime)}"); + stringBuilder.AppendLine($"{nameof(WiFiNetworkInfo.AvailableNetwork.Bssid)},{nameof(WiFiNetworkInfo.AvailableNetwork.Ssid)},{nameof(WiFiNetworkInfo.AvailableNetwork.ChannelCenterFrequencyInKilohertz)},{nameof(WiFiNetworkInfo.AvailableNetwork.SignalBars)},{nameof(WiFiNetworkInfo.AvailableNetwork.IsWiFiDirect)},{nameof(WiFiNetworkInfo.AvailableNetwork.NetworkRssiInDecibelMilliwatts)},{nameof(WiFiNetworkInfo.AvailableNetwork.PhyKind)},{nameof(WiFiNetworkInfo.AvailableNetwork.NetworkKind)},{nameof(WiFiNetworkInfo.AvailableNetwork.SecuritySettings.NetworkAuthenticationType)},{nameof(WiFiNetworkInfo.AvailableNetwork.SecuritySettings.NetworkEncryptionType)},{nameof(WiFiNetworkInfo.AvailableNetwork.BeaconInterval)}.{nameof(WiFiNetworkInfo.AvailableNetwork.Uptime)}"); foreach (var info in collection) - stringBuilder.AppendLine($"{info.BSSID},{info.SSID},{info.ChannelCenterFrequencyInKilohertz},{info.SignalBars},{info.IsWiFiDirect},{info.NetworkRssiInDecibelMilliwatts},{info.PhyKind},{info.NetworkKind},{info.AuthenticationType},{info.EncryptionType},{info.BeaconInterval},{info.Uptime}"); + stringBuilder.AppendLine($"{info.AvailableNetwork.Bssid},{info.AvailableNetwork.Ssid},{info.AvailableNetwork.ChannelCenterFrequencyInKilohertz},{info.AvailableNetwork.SignalBars},{info.AvailableNetwork.IsWiFiDirect},{info.AvailableNetwork.NetworkRssiInDecibelMilliwatts},{info.AvailableNetwork.PhyKind},{info.AvailableNetwork.NetworkKind},{info.AvailableNetwork.SecuritySettings.NetworkAuthenticationType},{info.AvailableNetwork.SecuritySettings.NetworkEncryptionType},{info.AvailableNetwork.BeaconInterval},{info.AvailableNetwork.Uptime}"); System.IO.File.WriteAllText(filePath, stringBuilder.ToString()); } @@ -390,7 +390,7 @@ private static void CreateCSV(IEnumerable collection, string var stringBuilder = new StringBuilder(); stringBuilder.AppendLine($"Status,{nameof(PingInfo.IPAddress)},{nameof(IPScannerHostInfo.Hostname)},PortStatus,PingStatus,{nameof(IPScannerHostInfo.MACAddress)},{nameof(IPScannerHostInfo.Vendor)},{nameof(IPScannerHostInfo.Ports)},{nameof(PingInfo.Bytes)},{nameof(PingInfo.Time)},{nameof(PingInfo.TTL)}"); - + foreach (var info in collection) { var stringBuilderPorts = new StringBuilder(); @@ -560,18 +560,18 @@ public static void CreateXML(IEnumerable collection, string fil from info in collection select new XElement(nameof(IPScannerHostInfo), - new XElement(nameof(WiFiNetworkInfo.BSSID), info.BSSID), - new XElement(nameof(WiFiNetworkInfo.SSID), info.SSID), - new XElement(nameof(WiFiNetworkInfo.ChannelCenterFrequencyInKilohertz), info.ChannelCenterFrequencyInKilohertz), - new XElement(nameof(WiFiNetworkInfo.SignalBars), info.SignalBars), - new XElement(nameof(WiFiNetworkInfo.IsWiFiDirect), info.IsWiFiDirect), - new XElement(nameof(WiFiNetworkInfo.NetworkRssiInDecibelMilliwatts), info.NetworkRssiInDecibelMilliwatts), - new XElement(nameof(WiFiNetworkInfo.PhyKind), info.PhyKind), - new XElement(nameof(WiFiNetworkInfo.NetworkKind), info.NetworkKind), - new XElement(nameof(WiFiNetworkInfo.AuthenticationType), info.AuthenticationType), - new XElement(nameof(WiFiNetworkInfo.EncryptionType), info.EncryptionType), - new XElement(nameof(WiFiNetworkInfo.BeaconInterval), info.BeaconInterval), - new XElement(nameof(WiFiNetworkInfo.Uptime), info.Uptime))))); + new XElement(nameof(WiFiNetworkInfo.AvailableNetwork.Bssid), info.AvailableNetwork.Bssid), + new XElement(nameof(WiFiNetworkInfo.AvailableNetwork.Ssid), info.AvailableNetwork.Ssid), + new XElement(nameof(WiFiNetworkInfo.AvailableNetwork.ChannelCenterFrequencyInKilohertz), info.AvailableNetwork.ChannelCenterFrequencyInKilohertz), + new XElement(nameof(WiFiNetworkInfo.AvailableNetwork.SignalBars), info.AvailableNetwork.SignalBars), + new XElement(nameof(WiFiNetworkInfo.AvailableNetwork.IsWiFiDirect), info.AvailableNetwork.IsWiFiDirect), + new XElement(nameof(WiFiNetworkInfo.AvailableNetwork.NetworkRssiInDecibelMilliwatts), info.AvailableNetwork.NetworkRssiInDecibelMilliwatts), + new XElement(nameof(WiFiNetworkInfo.AvailableNetwork.PhyKind), info.AvailableNetwork.PhyKind), + new XElement(nameof(WiFiNetworkInfo.AvailableNetwork.NetworkKind), info.AvailableNetwork.NetworkKind), + new XElement(nameof(WiFiNetworkInfo.AvailableNetwork.SecuritySettings.NetworkAuthenticationType), info.AvailableNetwork.SecuritySettings.NetworkAuthenticationType), + new XElement(nameof(WiFiNetworkInfo.AvailableNetwork.SecuritySettings.NetworkEncryptionType), info.AvailableNetwork.SecuritySettings.NetworkEncryptionType), + new XElement(nameof(WiFiNetworkInfo.AvailableNetwork.BeaconInterval), info.AvailableNetwork.BeaconInterval), + new XElement(nameof(WiFiNetworkInfo.AvailableNetwork.Uptime), info.AvailableNetwork.Uptime))))); document.Save(filePath); } @@ -851,18 +851,18 @@ public static void CreateJSON(ObservableCollection collection, { jsonData[i] = new { - collection[i].BSSID, - collection[i].SSID, - ChannelCenterFrequencyInKilohertz = collection[i].SSID.ToString(), - SignalBars = collection[i].SignalBars.ToString(), - IsWiFiDirect = collection[i].IsWiFiDirect.ToString(), - NetworkRssiInDecibelMilliwatts = collection[i].NetworkRssiInDecibelMilliwatts.ToString(), - PhyKind = collection[i].PhyKind.ToString(), - NetworkKind = collection[i].NetworkKind.ToString(), - AuthenticationType = collection[i].AuthenticationType.ToString(), - EncryptionType = collection[i].EncryptionType.ToString(), - BeaconInterval = collection[i].BeaconInterval.ToString(), - Uptime = collection[i].Uptime.ToString() + collection[i].AvailableNetwork.Bssid, + collection[i].AvailableNetwork.Ssid, + ChannelCenterFrequencyInKilohertz = collection[i].AvailableNetwork.Ssid.ToString(), + SignalBars = collection[i].AvailableNetwork.SignalBars.ToString(), + IsWiFiDirect = collection[i].AvailableNetwork.IsWiFiDirect.ToString(), + NetworkRssiInDecibelMilliwatts = collection[i].AvailableNetwork.NetworkRssiInDecibelMilliwatts.ToString(), + PhyKind = collection[i].AvailableNetwork.PhyKind.ToString(), + NetworkKind = collection[i].AvailableNetwork.NetworkKind.ToString(), + NetworkAuthenticationType = collection[i].AvailableNetwork.SecuritySettings.NetworkAuthenticationType.ToString(), + NetworkEncryptionType = collection[i].AvailableNetwork.SecuritySettings.NetworkEncryptionType.ToString(), + BeaconInterval = collection[i].AvailableNetwork.BeaconInterval.ToString(), + Uptime = collection[i].AvailableNetwork.Uptime.ToString() }; } diff --git a/Source/NETworkManager.Models/Generated Files/WinRTEventHelpers.cs b/Source/NETworkManager.Models/Generated Files/WinRTEventHelpers.cs index 29d0c942b1..d46743bd40 100644 --- a/Source/NETworkManager.Models/Generated Files/WinRTEventHelpers.cs +++ b/Source/NETworkManager.Models/Generated Files/WinRTEventHelpers.cs @@ -1,11 +1,12 @@ //------------------------------------------------------------------------------ // -// This file was generated by cswinrt.exe version 2.0.1.221115.1 +// This file was generated by cswinrt.exe version 2.0.2.230329.1 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // //------------------------------------------------------------------------------ +using System; namespace WinRT { diff --git a/Source/NETworkManager.Models/Network/DiscoveryProtocol.cs b/Source/NETworkManager.Models/Network/DiscoveryProtocol.cs index 62a85ec6a8..66dfca057c 100644 --- a/Source/NETworkManager.Models/Network/DiscoveryProtocol.cs +++ b/Source/NETworkManager.Models/Network/DiscoveryProtocol.cs @@ -105,7 +105,7 @@ public void CaptureAsync(int duration, Protocol protocol) powerShell.AddScript(PSDiscoveryProtocolModule); powerShell.AddScript($"Invoke-DiscoveryProtocolCapture -Duration {duration}" + (protocol != Protocol.LLDP_CDP ? $" -Type {protocol}" : "") + " -Force | Get-DiscoveryProtocolData"); - Collection PSOutput = powerShell.Invoke(); + Collection psOutputs = powerShell.Invoke(); if (powerShell.Streams.Error.Count > 0) { @@ -136,7 +136,7 @@ public void CaptureAsync(int duration, Protocol protocol) OnWarningReceived(new DiscoveryProtocolWarningArgs(stringBuilder.ToString())); } - foreach (PSObject outputItem in PSOutput) + foreach (PSObject outputItem in psOutputs) { if (outputItem == null) continue; diff --git a/Source/NETworkManager.Models/Network/NetworkInterface.cs b/Source/NETworkManager.Models/Network/NetworkInterface.cs index 3a48c7f140..1ef5e4a2f5 100644 --- a/Source/NETworkManager.Models/Network/NetworkInterface.cs +++ b/Source/NETworkManager.Models/Network/NetworkInterface.cs @@ -30,7 +30,7 @@ public static Task> GetNetworkInterfacesAsync() public static List GetNetworkInterfaces() { - var listNetworkInterfaceInfo = new List(); + List listNetworkInterfaceInfo = new(); foreach (var networkInterface in System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces()) { diff --git a/Source/NETworkManager.Models/Network/WiFi.cs b/Source/NETworkManager.Models/Network/WiFi.cs index 1a9392aebd..39f74ccc72 100644 --- a/Source/NETworkManager.Models/Network/WiFi.cs +++ b/Source/NETworkManager.Models/Network/WiFi.cs @@ -1,67 +1,243 @@ using System; using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Management.Automation; using System.Threading.Tasks; using Windows.Devices.WiFi; using Windows.Networking.Connectivity; +using Windows.Security.Credentials; //https://docs.microsoft.com/en-us/uwp/api/windows.devices.wifi.wifiadapter.requestaccessasync -//var access = await WiFiAdapter.RequestAccessAsync(); +//var access = await WiFiAdapter.RequestAccessAsync() == WiFiAccessStatus.Allowed; namespace NETworkManager.Models.Network; -public class WiFi +/// +/// Class with WiFi related methods. +/// +public static class WiFi { + /// + /// Get all WiFi adapters async with additional information from . + /// + /// with and as . public static async Task> GetAdapterAsync() { - List wifiAdapters = new List(); - List networkInterfaces = await NetworkInterface.GetNetworkInterfacesAsync(); + List wifiAdapterInfos = new(); - foreach (WiFiAdapter wifiAdapter in await WiFiAdapter.FindAllAdaptersAsync()) + IReadOnlyList wifiAdapters = await WiFiAdapter.FindAllAdaptersAsync(); + + if (wifiAdapters.Count > 0) { - foreach (NetworkInterfaceInfo networkInterface in networkInterfaces) + List networkInterfaces = await NetworkInterface.GetNetworkInterfacesAsync(); + + foreach (var wifiAdapter in wifiAdapters) { - if (!wifiAdapter.NetworkAdapter.NetworkAdapterId.ToString().Equals(networkInterface.Id.TrimStart('{').TrimEnd('}'), StringComparison.OrdinalIgnoreCase)) - continue; + var networkInteraceInfo = networkInterfaces.FirstOrDefault(x => x.Id.TrimStart('{').TrimEnd('}').Equals(wifiAdapter.NetworkAdapter.NetworkAdapterId.ToString(), StringComparison.OrdinalIgnoreCase)); - wifiAdapters.Add(new WiFiAdapterInfo + wifiAdapterInfos.Add(new WiFiAdapterInfo { - NetworkInterfaceInfo = networkInterface, + NetworkInterfaceInfo = networkInteraceInfo, WiFiAdapter = wifiAdapter }); } } - return wifiAdapters; + return wifiAdapterInfos; } - public static async Task> GetNetworksAsync(WiFiAdapter adapter) + /// + /// Get all available WiFi networks for an adapter with additional informations. + /// + /// WiFi adapter as . + /// A report as including a list of . + public static async Task GetNetworksAsync(WiFiAdapter adapter) { - List wifiNetworks = new List(); - + // Scan network adapter async await adapter.ScanAsync(); - foreach (var network in adapter.NetworkReport.AvailableNetworks) + // Try to get the current connected wifi network of this network adapter + var (ssid, bssid) = TryGetConnectedNetworkFromWiFiAdapter(adapter.NetworkAdapter.NetworkAdapterId.ToString()); + + List wifiNetworkInfos = new(); + + foreach (var availableNetwork in adapter.NetworkReport.AvailableNetworks) { - wifiNetworks.Add(new WiFiNetworkInfo() + wifiNetworkInfos.Add(new WiFiNetworkInfo() { - BSSID = network.Bssid, - SSID = network.Ssid, - ChannelCenterFrequencyInKilohertz = network.ChannelCenterFrequencyInKilohertz, - SignalBars = network.SignalBars, - IsWiFiDirect = network.IsWiFiDirect, - NetworkRssiInDecibelMilliwatts = network.NetworkRssiInDecibelMilliwatts, - PhyKind = network.PhyKind, - NetworkKind = network.NetworkKind, - AuthenticationType = network.SecuritySettings.NetworkAuthenticationType, - EncryptionType = network.SecuritySettings.NetworkEncryptionType, - BeaconInterval = network.BeaconInterval, - Uptime = network.Uptime + AvailableNetwork = availableNetwork, + IsHidden = string.IsNullOrEmpty(availableNetwork.Ssid), + IsConnected = availableNetwork.Bssid.Equals(bssid, StringComparison.OrdinalIgnoreCase) }); } - return wifiNetworks; + return new WiFiNetworkScanInfo() + { + NetworkAdapterId = adapter.NetworkAdapter.NetworkAdapterId, + WiFiNetworkInfos = wifiNetworkInfos, + Timestamp = adapter.NetworkReport.Timestamp.LocalDateTime + }; + } + + /// + /// Try to get the current connected wifi network (SSID and BSSID) of a network adapter from + /// netsh.exe. + /// + /// Calling netsh.exe and parsing the output feels so dirty, but Microsoft's API returns only + /// the WLAN profile and the SSID of the connected network. The BSSID is needed to find a + /// specific access point among several. + /// + /// GUID of the WiFi network adapter. + /// SSID and BSSID of the connected wifi network. Values are null if not detected. + private static (string SSID, string BSSID) TryGetConnectedNetworkFromWiFiAdapter(string adapterId) + { + string ssid = null; + string bssid = null; + + using (System.Management.Automation.PowerShell powerShell = System.Management.Automation.PowerShell.Create()) + { + powerShell.AddScript("netsh wlan show interfaces"); + + Collection psOutputs = powerShell.Invoke(); + + /* + if (powerShell.Streams.Error.Count > 0) { // Handle error? } + if (powerShell.Streams.Warning.Count > 0) { // Handle warning? } + */ + + /* Each object looks like this: + * + * Name : Wireless + * Description : Intel ... + * GUID : 90d8... + * SSID : Devices + * BSSID : 6a:d7:... + */ + + bool foundAdapter = false; + + foreach (PSObject outputItem in psOutputs) + { + // Find line with the network adapter id... + if (outputItem.ToString().Contains(adapterId, StringComparison.OrdinalIgnoreCase)) + foundAdapter = true; + + if (foundAdapter) + { + // Extract SSID from the line + if (outputItem.ToString().Contains(" SSID ", StringComparison.OrdinalIgnoreCase)) + ssid = outputItem.ToString().Split(':')[1].Trim(); + + // Extract BSSID from the line + if (outputItem.ToString().Contains(" BSSID ", StringComparison.OrdinalIgnoreCase)) + bssid = outputItem.ToString().Split(':', 2)[1].Trim(); + + // Break if we got the values, otherwise we might overwrite them + // with values from another adapter. + if (!string.IsNullOrEmpty(ssid) && !string.IsNullOrEmpty(bssid)) + break; + } + } + } + + return (ssid, bssid); } + /// + /// Connect to a WiFi network with Pre-shared key, EAP or no security. + /// + /// WiFi adapter which should be used for the connection. + /// WiFi network to connect to. + /// Reconnection type to automatically or manuel reconnect. + /// Credentials for EAP or PSK. Empty for open networks. + /// SSID for hidden networks. + /// + public static async Task ConnectAsync(WiFiAdapter adapter, WiFiAvailableNetwork network, WiFiReconnectionKind reconnectionKind, PasswordCredential credential, string ssid = null) + { + WiFiConnectionResult connectionResult; + + if (string.IsNullOrEmpty(ssid)) + connectionResult = await adapter.ConnectAsync(network, reconnectionKind, credential); + else + connectionResult = await adapter.ConnectAsync(network, reconnectionKind, credential, ssid); + + // Wrong password may cause connection to timeout. + // Disconnect any network from the adapter to return it to a non-busy state. + if (connectionResult.ConnectionStatus == WiFiConnectionStatus.Timeout) + Disconnect(adapter); + + return connectionResult.ConnectionStatus; + } + + /// + /// Connect to a WiFi network with WPS push button. + /// + /// WiFi adapter which should be used for the connection. + /// WiFi network to connect to. + /// Reconnection type to automatically or manuel reconnect. + /// + public static async Task ConnectWpsAsync(WiFiAdapter adapter, WiFiAvailableNetwork network, WiFiReconnectionKind reconnectionKind) + { + WiFiConnectionResult connectionResult = await adapter.ConnectAsync(network, reconnectionKind, null, string.Empty, WiFiConnectionMethod.WpsPushButton); + + // Wrong password may cause connection to timeout. + // Disconnect any network from the adapter to return it to a non-busy state. + if (connectionResult.ConnectionStatus == WiFiConnectionStatus.Timeout) + Disconnect(adapter); + + return connectionResult.ConnectionStatus; + } + + /// + /// Disconnect the wifi adapter from the current wifi network. + /// + /// WiFi adapter from which the wifi network should be disconnected. + public static void Disconnect(WiFiAdapter adapter) + { + adapter.Disconnect(); + } + + /// + /// Get the connect mode of a wifi network like Open, Eap (WPA2-Enterprise) + /// or Psk (WPA2-Personal). + /// + /// WiFi network as . + /// Connect mode as . + public static WiFiConnectMode GetConnectMode(WiFiAvailableNetwork network) + { + // Enterprise + if (network.SecuritySettings.NetworkAuthenticationType == NetworkAuthenticationType.Rsna || + network.SecuritySettings.NetworkAuthenticationType == NetworkAuthenticationType.Wpa) + return WiFiConnectMode.Eap; + + // Open + if (network.SecuritySettings.NetworkAuthenticationType == NetworkAuthenticationType.Open80211 || + network.SecuritySettings.NetworkEncryptionType == NetworkEncryptionType.None) + return WiFiConnectMode.Open; + + // Pre-Shared-Key + return WiFiConnectMode.Psk; + } + + /// + /// Check if WPS is available for a wifi network. + /// + /// WiFi adapter as . + /// WiFi network as . + /// + public static async Task IsWpsAvailable(WiFiAdapter adapter, WiFiAvailableNetwork network) + { + var result = await adapter.GetWpsConfigurationAsync(network); + + return result.SupportedWpsKinds.Contains(WiFiWpsKind.PushButton); + } + + /// + /// Get the WiFi channel from channel frequency. + /// + /// Input like 2422000 or 5240000. + /// WiFi channel like 3 or 48. public static int GetChannelFromChannelFrequency(int kilohertz) { return (double)ConvertChannelFrequencyToGigahertz(kilohertz) switch @@ -110,11 +286,21 @@ public static int GetChannelFromChannelFrequency(int kilohertz) }; } + /// + /// Convert the channel frequency to gigahertz. + /// + /// Frequency in kilohertz like 2422000 or 5240000. + /// Frequency in gigahertz like 2.422 or 5.240. public static double ConvertChannelFrequencyToGigahertz(int kilohertz) { return Convert.ToDouble(kilohertz) / 1000 / 1000; } + /// + /// Check if the WiFi network is a 2.4 GHz network. + /// + /// Frequency in kilohertz like 2422000 or 5240000. + /// True if WiFi network is 2.4 GHz. public static bool Is2dot4GHzNetwork(int kilohertz) { var x = ConvertChannelFrequencyToGigahertz(kilohertz); @@ -122,6 +308,11 @@ public static bool Is2dot4GHzNetwork(int kilohertz) return x >= 2.412 && x <= 2.472; } + /// + /// Check if the WiFi network is a 5 GHz network. + /// + /// Frequency in kilohertz like 2422000 or 5240000. + /// True if WiFi network is 5 GHz. public static bool Is5GHzNetwork(int kilohertz) { var x = ConvertChannelFrequencyToGigahertz(kilohertz); @@ -129,6 +320,11 @@ public static bool Is5GHzNetwork(int kilohertz) return x >= 5.180 && x <= 5.825; } + /// + /// Get the human readable network authentication type. + /// + /// WiFi network authentication type as . + /// Human readable autentication type as string like "Open" or "WPA2 Enterprise". public static string GetHumanReadableNetworkAuthenticationType(NetworkAuthenticationType networkAuthenticationType) { return networkAuthenticationType switch @@ -147,6 +343,11 @@ public static string GetHumanReadableNetworkAuthenticationType(NetworkAuthentica }; } + /// + /// Get the human readable network phy kind. + /// + /// WiFi network phy kind as . + /// Human readable phy kind as string like "802.11g" or "802.11ax". public static string GetHumandReadablePhyKind(WiFiPhyKind phyKind) { return phyKind switch @@ -162,10 +363,4 @@ public static string GetHumandReadablePhyKind(WiFiPhyKind phyKind) _ => "-/-", }; } - - public enum Radio - { - One, - Two - } } \ No newline at end of file diff --git a/Source/NETworkManager.Models/Network/WiFiConnectMode.cs b/Source/NETworkManager.Models/Network/WiFiConnectMode.cs new file mode 100644 index 0000000000..5fed34f167 --- /dev/null +++ b/Source/NETworkManager.Models/Network/WiFiConnectMode.cs @@ -0,0 +1,24 @@ +namespace NETworkManager.Models.Network; + +/// +/// Enum for the WiFi connect mode. +/// +public enum WiFiConnectMode +{ + /// + /// WiFi network is open. + /// + Open, + + /// + /// WiFi network is protected with Pre-Shared Key (PSK). + /// E.g WpaPsk or RsnaPsk. + /// + Psk, + + /// + /// WiFi network is protected with User-Password-Authentication (EAP). + /// E.g. Wpa or Rsna. + /// + Eap +} diff --git a/Source/NETworkManager.Models/Network/WiFiNetworkInfo.cs b/Source/NETworkManager.Models/Network/WiFiNetworkInfo.cs index d3f8569015..59ab76be8d 100644 --- a/Source/NETworkManager.Models/Network/WiFiNetworkInfo.cs +++ b/Source/NETworkManager.Models/Network/WiFiNetworkInfo.cs @@ -1,39 +1,35 @@ -using System; -using System.ComponentModel; -using System.Runtime.CompilerServices; -using Windows.Devices.WiFi; -using Windows.Networking.Connectivity; +using Windows.Devices.WiFi; namespace NETworkManager.Models.Network; -public class WiFiNetworkInfo : INotifyPropertyChanged + +/// +/// Class contains information about a WiFi network. +/// +public class WiFiNetworkInfo { - #region PropertyChangedEventHandler - public event PropertyChangedEventHandler PropertyChanged; + #region Variables + /// + /// Informations about an available WiFi network. + /// + public WiFiAvailableNetwork AvailableNetwork { get; set; } - protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) - { - PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); - } - #endregion + /// + /// Indicates if the WiFi network Ssid is hidden. + /// + public bool IsHidden { get; set; } - #region Variables - public string BSSID { get; set; } - public string SSID { get; set; } - public int ChannelCenterFrequencyInKilohertz { get; set; } - public byte SignalBars { get; set; } - public bool IsWiFiDirect { get; set; } - public double NetworkRssiInDecibelMilliwatts { get; set; } - public WiFiPhyKind PhyKind { get; set; } - public WiFiNetworkKind NetworkKind { get; set; } - public NetworkAuthenticationType AuthenticationType { get; set; } - public NetworkEncryptionType EncryptionType { get; set; } - public TimeSpan BeaconInterval { get; set; } - public TimeSpan Uptime { get; set; } + /// + /// Indicates if the WiFi network is connected to the current WiFi adapter. + /// + public bool IsConnected { get; set; } #endregion + /// + /// /// Create an instance of . + /// public WiFiNetworkInfo() { - + } } diff --git a/Source/NETworkManager.Models/Network/WiFiNetworkScannfo.cs b/Source/NETworkManager.Models/Network/WiFiNetworkScannfo.cs new file mode 100644 index 0000000000..ec5298e3ef --- /dev/null +++ b/Source/NETworkManager.Models/Network/WiFiNetworkScannfo.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; + +namespace NETworkManager.Models.Network; + +/// +/// Class contains information about a WiFi network scan. +/// +public class WiFiNetworkScanInfo +{ + #region Variables + /// + /// If of the network adapter who performed the scan. + /// + public Guid NetworkAdapterId { get; set; } + + /// + /// List of available WiFi networks on the network adapter. + /// + public List WiFiNetworkInfos { get; set; } + + /// + /// Timestamp when the scan was performed. + /// + public DateTime Timestamp { get; set; } + #endregion + + /// + /// Create an instance of . + /// + public WiFiNetworkScanInfo() + { + + } +} diff --git a/Source/NETworkManager.Models/Network/WiFiRadio.cs b/Source/NETworkManager.Models/Network/WiFiRadio.cs new file mode 100644 index 0000000000..ce2535fc31 --- /dev/null +++ b/Source/NETworkManager.Models/Network/WiFiRadio.cs @@ -0,0 +1,7 @@ +namespace NETworkManager.Models.Network; + +public enum WiFiRadio +{ + One, + Two +} diff --git a/Source/NETworkManager/Generated Files/WinRTEventHelpers.cs b/Source/NETworkManager/Generated Files/WinRTEventHelpers.cs index 29d0c942b1..d46743bd40 100644 --- a/Source/NETworkManager/Generated Files/WinRTEventHelpers.cs +++ b/Source/NETworkManager/Generated Files/WinRTEventHelpers.cs @@ -1,11 +1,12 @@ //------------------------------------------------------------------------------ // -// This file was generated by cswinrt.exe version 2.0.1.221115.1 +// This file was generated by cswinrt.exe version 2.0.2.230329.1 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // //------------------------------------------------------------------------------ +using System; namespace WinRT { diff --git a/Source/NETworkManager/ViewModels/CredentialsChangePasswordViewModel.cs b/Source/NETworkManager/ViewModels/CredentialsChangePasswordViewModel.cs index 7c0f978f13..22198d51e1 100644 --- a/Source/NETworkManager/ViewModels/CredentialsChangePasswordViewModel.cs +++ b/Source/NETworkManager/ViewModels/CredentialsChangePasswordViewModel.cs @@ -20,10 +20,10 @@ public class CredentialsChangePasswordViewModel : ViewModelBase /// /// Private variable for . /// - private SecureString _password = new SecureString(); + private SecureString _password = new(); /// - /// Password as secure string. + /// Password as . /// public SecureString Password { @@ -44,10 +44,10 @@ public SecureString Password /// /// Private variable for . /// - private SecureString _newPassword = new SecureString(); + private SecureString _newPassword = new(); /// - /// New password as secure string. + /// New password as . /// public SecureString NewPassword { @@ -68,10 +68,10 @@ public SecureString NewPassword /// /// Private variable for . /// - private SecureString _newPasswordRepeat = new SecureString(); + private SecureString _newPasswordRepeat = new(); /// - /// Repeated new password as secure string. + /// Repeated new password as . /// public SecureString NewPasswordRepeat { diff --git a/Source/NETworkManager/ViewModels/CredentialsPasswordProfileFileViewModel.cs b/Source/NETworkManager/ViewModels/CredentialsPasswordProfileFileViewModel.cs index 4ebe284898..ee4a01d461 100644 --- a/Source/NETworkManager/ViewModels/CredentialsPasswordProfileFileViewModel.cs +++ b/Source/NETworkManager/ViewModels/CredentialsPasswordProfileFileViewModel.cs @@ -65,7 +65,7 @@ public bool ShowWrongPassword private SecureString _password = new(); /// - /// Password as secure string. + /// Password as . /// public SecureString Password { @@ -86,7 +86,7 @@ public SecureString Password /// /// Private variable for . /// - private bool _isPasswordEmpty; + private bool _isPasswordEmpty = true; /// /// Indicate if one of the password fields are empty. diff --git a/Source/NETworkManager/ViewModels/CredentialsPasswordViewModel.cs b/Source/NETworkManager/ViewModels/CredentialsPasswordViewModel.cs index b5b0bce730..df9ca0cfad 100644 --- a/Source/NETworkManager/ViewModels/CredentialsPasswordViewModel.cs +++ b/Source/NETworkManager/ViewModels/CredentialsPasswordViewModel.cs @@ -20,10 +20,10 @@ public class CredentialsPasswordViewModel : ViewModelBase /// /// Private variable for . /// - private SecureString _password = new SecureString(); + private SecureString _password = new(); /// - /// Password as secure string. + /// Password as . /// public SecureString Password { @@ -44,7 +44,7 @@ public SecureString Password /// /// Private variable for . /// - private bool _isPasswordEmpty; + private bool _isPasswordEmpty = true; /// /// Indicate if one of the password fields are empty. @@ -61,8 +61,7 @@ public bool IsPasswordEmpty OnPropertyChanged(); } } - - + /// /// Initalizes a new class with and . /// diff --git a/Source/NETworkManager/ViewModels/CredentialsSetPasswordViewModel.cs b/Source/NETworkManager/ViewModels/CredentialsSetPasswordViewModel.cs index 89b736f127..aeeb56b753 100644 --- a/Source/NETworkManager/ViewModels/CredentialsSetPasswordViewModel.cs +++ b/Source/NETworkManager/ViewModels/CredentialsSetPasswordViewModel.cs @@ -20,10 +20,10 @@ public class CredentialsSetPasswordViewModel : ViewModelBase /// /// Private variable for . /// - private SecureString _password = new SecureString(); + private SecureString _password = new(); /// - /// Password as secure string. + /// Password as . /// public SecureString Password { @@ -44,10 +44,10 @@ public SecureString Password /// /// Private variable for . /// - private SecureString _passwordRepeat = new SecureString(); + private SecureString _passwordRepeat = new(); /// - /// Repeated password as secure string. + /// Repeated password as . /// public SecureString PasswordRepeat { diff --git a/Source/NETworkManager/ViewModels/PingMonitorSettingsViewModel.cs b/Source/NETworkManager/ViewModels/PingMonitorSettingsViewModel.cs index 7042128564..0c8ae45f9e 100644 --- a/Source/NETworkManager/ViewModels/PingMonitorSettingsViewModel.cs +++ b/Source/NETworkManager/ViewModels/PingMonitorSettingsViewModel.cs @@ -112,4 +112,4 @@ private void LoadSettings() WaitTime = SettingsManager.Current.PingMonitor_WaitTime; } #endregion -} \ No newline at end of file +} diff --git a/Source/NETworkManager/ViewModels/WiFiConnectViewModel.cs b/Source/NETworkManager/ViewModels/WiFiConnectViewModel.cs new file mode 100644 index 0000000000..f5dfa8cad9 --- /dev/null +++ b/Source/NETworkManager/ViewModels/WiFiConnectViewModel.cs @@ -0,0 +1,354 @@ +using NETworkManager.Utilities; +using System; +using System.Security; +using System.Windows.Input; +using NETworkManager.Models.Network; +using System.Threading.Tasks; + +namespace NETworkManager.ViewModels; + +public class WiFiConnectViewModel : ViewModelBase +{ + /// + /// Command which is called when the Connect button is clicked. + /// + public ICommand ConnectCommand { get; } + + /// + /// Command which is called when the Connect WPS button is clicked. + /// + public ICommand ConnectWpsCommand { get; } + + /// + /// Command which is called when the cancel button is clicked. + /// + public ICommand CancelCommand { get; } + + /// + /// Current WiFi adapter info and network info. + /// + public readonly (WiFiAdapterInfo AdapterInfo, WiFiNetworkInfo NetworkInfo) Options; + + /// + /// Private variable for . + /// + private WiFiConnectMode _connectMode; + + /// + /// WiFi connect mode like , or . + /// + public WiFiConnectMode ConnectMode + { + get => _connectMode; + set + { + if (value == _connectMode) + return; + + _connectMode = value; + OnPropertyChanged(); + } + } + + /// + /// Private variable for . + /// + private bool _isSsidRequired; + + /// + /// Indicate if the SSID field is required. + /// This is the case for hidden networks. + /// + public bool IsSsidRequired + { + get => _isSsidRequired; + set + { + if (value == _isSsidRequired) + return; + + _isSsidRequired = value; + OnPropertyChanged(); + } + } + + /// + /// Private variable for . + /// + private string _ssid; + + /// + /// SSID of the network. + /// + public string Ssid + { + get => _ssid; + set + { + if (value == _ssid) + return; + + _ssid = value; + OnPropertyChanged(); + } + } + + /// + /// Private variable for . + /// + private bool _connectAutomatically; + + /// + /// Indicate if the network should be connected automatically. + /// + public bool ConnectAutomatically + { + get => _connectAutomatically; + set + { + if (value == _connectAutomatically) + return; + + _connectAutomatically = value; + OnPropertyChanged(); + } + } + + /// + /// Private variable for . + /// + private SecureString _preSharedKey = new(); + + /// + /// Pre-shared key as . + /// + public SecureString PreSharedKey + { + get => _preSharedKey; + set + { + if (value == _preSharedKey) + return; + + _preSharedKey = value; + + ValidatePreSharedKey(); + + OnPropertyChanged(); + } + } + + /// + /// Private variable for . + /// + private bool _isPreSharedKeyEmpty = true; + + /// + /// Indicate if the Pre-shared-key field is empty. + /// + public bool IsPreSharedKeyEmpty + { + get => _isPreSharedKeyEmpty; + set + { + if (value == _isPreSharedKeyEmpty) + return; + + _isPreSharedKeyEmpty = value; + OnPropertyChanged(); + } + } + + /// + /// Private variable for . + /// + private bool _useCredentials = true; + + /// + /// Use credentials for EAP authentication. + /// + public bool UseCredentials + { + get => _useCredentials; + set + { + if (value == _useCredentials) + return; + + _useCredentials = value; + OnPropertyChanged(); + } + } + + /// + /// Private variable for . + /// + private string _username; + + /// + /// Username for EAP authentication. + /// + public string Username + { + get => _username; + set + { + if (value == _username) + return; + + _username = value; + OnPropertyChanged(); + } + } + + /// + /// Private variable for . + /// + private string _domain; + + /// + /// Domain for EAP authentication. + /// + public string Domain + { + get => _domain; + set + { + if (value == _domain) + return; + + _domain = value; + OnPropertyChanged(); + } + } + + /// + /// Private variable for . + /// + private SecureString _password = new(); + + /// + /// Password as for EAP authentication. + /// + public SecureString Password + { + get => _password; + set + { + if (value == _password) + return; + + _password = value; + + ValidatePassword(); + + OnPropertyChanged(); + } + } + + /// + /// Private variable for . + /// + private bool _isPasswordEmpty = true; + + /// + /// Indicate if the password field is empty. + /// + public bool IsPasswordEmpty + { + get => _isPasswordEmpty; + set + { + if (value == _isPasswordEmpty) + return; + + _isPasswordEmpty = value; + OnPropertyChanged(); + } + } + + /// + /// Private variable for . + /// + private bool _isWpsChecking; + + /// + /// Checking if WPS is available for the network. + /// + public bool IsWpsChecking + { + get => _isWpsChecking; + set + { + if (value == _isWpsChecking) + return; + + _isWpsChecking = value; + OnPropertyChanged(); + } + } + + /// + /// Private variable for . + /// + private bool _isWpsAvailable; + + /// + /// Indicate if WPS is available for the network. + /// + public bool IsWpsAvailable + { + get => _isWpsAvailable; + set + { + if (value == _isWpsAvailable) + return; + + _isWpsAvailable = value; + OnPropertyChanged(); + } + } + + /// + /// Initalizes a new class with and . + /// + /// which is executed on OK click. + /// which is executed on cancel click. + public WiFiConnectViewModel(Action okCommand, Action connectWpsCommand, Action cancelHandler, (WiFiAdapterInfo AdapterInfo, WiFiNetworkInfo NetworkInfo) options, WiFiConnectMode connectMode) + { + ConnectCommand = new RelayCommand(p => okCommand(this)); + ConnectWpsCommand = new RelayCommand(p => connectWpsCommand(this)); + CancelCommand = new RelayCommand(p => cancelHandler(this)); + + Options = options; + ConnectMode = connectMode; + + // Get Ssid to connect to hidden network + IsSsidRequired = Options.NetworkInfo.IsHidden; + } + + public async Task CheckWpsAsync() + { + // Only check if WPS is available for networks secured by Pre-shared key who are not hidden + if (ConnectMode != WiFiConnectMode.Psk || Options.NetworkInfo.IsHidden) + return; + + IsWpsChecking = true; + await Task.Delay(1000); // Show animation ;) + + IsWpsAvailable = await WiFi.IsWpsAvailable(Options.AdapterInfo.WiFiAdapter, Options.NetworkInfo.AvailableNetwork); + + await Task.Delay(1000); // Show animation ;) + IsWpsChecking = false; + } + + /// + /// Check if the Pre-shared key is valid. + /// + private void ValidatePreSharedKey() => IsPreSharedKeyEmpty = PreSharedKey == null || PreSharedKey.Length == 0; + + /// + /// Check if the password is valid. + /// + private void ValidatePassword() => IsPasswordEmpty = Password == null || Password.Length == 0; +} diff --git a/Source/NETworkManager/ViewModels/WiFiViewModel.cs b/Source/NETworkManager/ViewModels/WiFiViewModel.cs index 93356e4723..5a9ba37a29 100644 --- a/Source/NETworkManager/ViewModels/WiFiViewModel.cs +++ b/Source/NETworkManager/ViewModels/WiFiViewModel.cs @@ -1,6 +1,7 @@ using LiveCharts; using LiveCharts.Wpf; using MahApps.Metro.Controls.Dialogs; +using NETworkManager.Localization.Translators; using NETworkManager.Models.Export; using NETworkManager.Models.Lookup; using NETworkManager.Models.Network; @@ -15,11 +16,11 @@ using System.IO; using System.Linq; using System.Threading.Tasks; -using System.Windows.Automation.Peers; using System.Windows.Data; using System.Windows.Input; using System.Windows.Threading; using Windows.Devices.WiFi; +using Windows.Security.Credentials; namespace NETworkManager.ViewModels; @@ -30,6 +31,7 @@ public class WiFiViewModel : ViewModelBase private readonly bool _isLoading; private readonly DispatcherTimer _autoRefreshTimer = new(); + private readonly DispatcherTimer _hideConnectionStatusMessageTimer = new(); private bool _sdkContractsFailedToLoad; public bool SDKContractsFailedToLoad @@ -87,7 +89,7 @@ public WiFiAdapterInfo SelectedAdapter if (!_isLoading) SettingsManager.Current.WiFi_InterfaceId = value.NetworkInterfaceInfo.Id; - Scan(value.WiFiAdapter); + Scan(value); } _selectedAdapters = value; @@ -312,6 +314,48 @@ public string StatusMessage OnPropertyChanged(); } } + + private bool _isConnecting; + public bool IsConnecting + { + get => _isConnecting; + set + { + if (value == _isConnecting) + return; + + _isConnecting = value; + OnPropertyChanged(); + } + } + + private bool _isConnectionStatusMessageDisplayed; + public bool IsConnectionStatusMessageDisplayed + { + get => _isConnectionStatusMessageDisplayed; + set + { + if (value == _isConnectionStatusMessageDisplayed) + return; + + _isConnectionStatusMessageDisplayed = value; + OnPropertyChanged(); + } + } + + private string _connectionStatusMessage; + public string ConnectionStatusMessage + { + get => _connectionStatusMessage; + set + { + if (value == _connectionStatusMessage) + return; + + _connectionStatusMessage = value; + OnPropertyChanged(); + } + } #endregion #region Constructor, load settings @@ -323,28 +367,27 @@ public WiFiViewModel(IDialogCoordinator instance) // Result view + search NetworksView = CollectionViewSource.GetDefaultView(Networks); - NetworksView.SortDescriptions.Add(new SortDescription(nameof(WiFiNetworkInfo.SSID), ListSortDirection.Ascending)); + NetworksView.SortDescriptions.Add(new SortDescription($"{nameof(WiFiNetworkInfo.AvailableNetwork)}.{nameof(WiFiNetworkInfo.AvailableNetwork.Ssid)}", ListSortDirection.Ascending)); NetworksView.Filter = o => { if (o is WiFiNetworkInfo info) { - if (WiFi.Is2dot4GHzNetwork(info.ChannelCenterFrequencyInKilohertz) && !Show2dot4GHzNetworks) + if (WiFi.Is2dot4GHzNetwork(info.AvailableNetwork.ChannelCenterFrequencyInKilohertz) && !Show2dot4GHzNetworks) return false; - if (WiFi.Is5GHzNetwork(info.ChannelCenterFrequencyInKilohertz) && !Show5GHzNetworks) + if (WiFi.Is5GHzNetwork(info.AvailableNetwork.ChannelCenterFrequencyInKilohertz) && !Show5GHzNetworks) return false; if (string.IsNullOrEmpty(Search)) return true; - // Search by: SSID, Security, Channel, BSSID (MAC address), Vendor, Phy kind - return info.SSID.IndexOf(Search, StringComparison.OrdinalIgnoreCase) > -1 || - WiFi.GetHumanReadableNetworkAuthenticationType(info.AuthenticationType).IndexOf(Search, StringComparison.OrdinalIgnoreCase) > -1 || - $"{WiFi.GetChannelFromChannelFrequency(info.ChannelCenterFrequencyInKilohertz)}".IndexOf(Search, StringComparison.OrdinalIgnoreCase) > -1 || - info.BSSID.IndexOf(Search, StringComparison.OrdinalIgnoreCase) > -1 || - OUILookup.Lookup(info.BSSID).FirstOrDefault()?.Vendor.IndexOf(Search, StringComparison.OrdinalIgnoreCase) > -1 || - WiFi.GetHumandReadablePhyKind(info.PhyKind).IndexOf(Search, StringComparison.OrdinalIgnoreCase) > -1; + return info.AvailableNetwork.Ssid.IndexOf(Search, StringComparison.OrdinalIgnoreCase) > -1 || + WiFi.GetHumanReadableNetworkAuthenticationType(info.AvailableNetwork.SecuritySettings.NetworkAuthenticationType).IndexOf(Search, StringComparison.OrdinalIgnoreCase) > -1 || + $"{WiFi.GetChannelFromChannelFrequency(info.AvailableNetwork.ChannelCenterFrequencyInKilohertz)}".IndexOf(Search, StringComparison.OrdinalIgnoreCase) > -1 || + info.AvailableNetwork.Bssid.IndexOf(Search, StringComparison.OrdinalIgnoreCase) > -1 || + OUILookup.Lookup(info.AvailableNetwork.Bssid).FirstOrDefault()?.Vendor.IndexOf(Search, StringComparison.OrdinalIgnoreCase) > -1 || + WiFi.GetHumandReadablePhyKind(info.AvailableNetwork.PhyKind).IndexOf(Search, StringComparison.OrdinalIgnoreCase) > -1; } else { @@ -362,6 +405,10 @@ public WiFiViewModel(IDialogCoordinator instance) SelectedAutoRefreshTime = AutoRefreshTimes.Cast().FirstOrDefault(x => x.Value == SettingsManager.Current.WiFi_AutoRefreshTime.Value && x.TimeUnit == SettingsManager.Current.WiFi_AutoRefreshTime.TimeUnit); AutoRefreshEnabled = SettingsManager.Current.WiFi_AutoRefreshEnabled; + // Hide ConnectionStatusMessage automatically + _hideConnectionStatusMessageTimer.Interval = new TimeSpan(0, 0, 15); + _hideConnectionStatusMessageTimer.Tick += HideConnectionStatusMessageTimer_Tick; + // Load settings LoadSettings(); @@ -376,9 +423,7 @@ private void LoadSettings() #endregion #region ICommands & Actions - public ICommand ReloadAdaptersCommand => new RelayCommand(p => ReloadAdapterAction(), ReloadAdapters_CanExecute); - - private bool ReloadAdapters_CanExecute(object obj) => !IsAdaptersLoading; + public ICommand ReloadAdaptersCommand => new RelayCommand(p => ReloadAdapterAction()); private void ReloadAdapterAction() { @@ -387,11 +432,24 @@ private void ReloadAdapterAction() public ICommand ScanNetworksCommand => new RelayCommand(p => ScanNetworksAction(), ScanNetworks_CanExecute); - private bool ScanNetworks_CanExecute(object obj) => !IsAdaptersLoading && !IsNetworksLoading; + private bool ScanNetworks_CanExecute(object obj) => !IsAdaptersLoading && !IsNetworksLoading && !IsBackgroundSearchRunning && !IsConnecting; private async Task ScanNetworksAction() { - await Scan(SelectedAdapter.WiFiAdapter, true); + await Scan(SelectedAdapter, true); + } + + public ICommand ConnectCommand => new RelayCommand(p => ConnectAction()); + + private void ConnectAction() + { + Connect(); + } + public ICommand DisconnectCommand => new RelayCommand(p => DisconnectAction()); + + private void DisconnectAction() + { + Disconnect(); } public ICommand ExportCommand => new RelayCommand(p => ExportAction()); @@ -429,7 +487,7 @@ private async Task LoadAdapters(string adapterId = null) IsAdaptersLoading = false; } - private async Task Scan(WiFiAdapter adapter, bool refreshing = false) + private async Task Scan(WiFiAdapterInfo adapterInfo, bool refreshing = false, uint delayInMS = 0) { if (refreshing) { @@ -442,51 +500,66 @@ private async Task Scan(WiFiAdapter adapter, bool refreshing = false) IsNetworksLoading = true; } - IEnumerable networks = await WiFi.GetNetworksAsync(adapter); + if (delayInMS != 0) + await Task.Delay((int)delayInMS); - Networks.Clear(); + string statusMessage = string.Empty; - Radio1Series.Clear(); - Radio2Series.Clear(); - - foreach (var network in networks) + try { - // Identify hidden networks - if (string.IsNullOrEmpty(network.SSID)) - network.SSID = Localization.Resources.Strings.HiddenNetwork; + WiFiNetworkScanInfo wiFiNetworkScanInfo = await WiFi.GetNetworksAsync(adapterInfo.WiFiAdapter); - Networks.Add(network); + // Clear the values after the scan to make the UI smoother + Networks.Clear(); + Radio1Series.Clear(); + Radio2Series.Clear(); - if (WiFi.ConvertChannelFrequencyToGigahertz(network.ChannelCenterFrequencyInKilohertz) < 5) // 2.4 GHz - AddNetworkToRadio1Chart(network); - else - AddNetworkToRadio2Chart(network); + foreach (var network in wiFiNetworkScanInfo.WiFiNetworkInfos) + { + Networks.Add(network); + + if (WiFi.ConvertChannelFrequencyToGigahertz(network.AvailableNetwork.ChannelCenterFrequencyInKilohertz) < 5) // 2.4 GHz + Radio1Series.Add(GetSeriesCollection(network, WiFiRadio.One)); + else + Radio2Series.Add(GetSeriesCollection(network, WiFiRadio.Two)); + } + + statusMessage = string.Format(Localization.Resources.Strings.LastScanAtX, wiFiNetworkScanInfo.Timestamp.ToLongTimeString()); } + catch (Exception ex) + { + // Clear the existing old values if an error occours + Networks.Clear(); + Radio1Series.Clear(); + Radio2Series.Clear(); - IsStatusMessageDisplayed = true; - StatusMessage = string.Format(Localization.Resources.Strings.LastScanAtX, DateTime.Now.ToLongTimeString()); + statusMessage = string.Format(Localization.Resources.Strings.ErrorWhileScanningWiFiAdapterXXXWithErrorXXX, adapterInfo.NetworkInterfaceInfo.Name, ex.Message); + } + finally + { + IsStatusMessageDisplayed = true; + StatusMessage = statusMessage; - if (refreshing) IsBackgroundSearchRunning = false; - else IsNetworksLoading = false; + } } - private ChartValues GetDefaultChartValues(WiFi.Radio radio) + private ChartValues GetDefaultChartValues(WiFiRadio radio) { ChartValues values = new(); - for (int i = 0; i < (radio == WiFi.Radio.One ? Radio1Labels.Length : Radio2Labels.Length); i++) + for (int i = 0; i < (radio == WiFiRadio.One ? Radio1Labels.Length : Radio2Labels.Length); i++) values.Add(-1); return values; } - private ChartValues SetChartValues(WiFiNetworkInfo network, WiFi.Radio radio, int index) + private ChartValues GetChartValues(WiFiNetworkInfo network, WiFiRadio radio, int index) { ChartValues values = GetDefaultChartValues(radio); - double reverseMilliwatts = 100 - (network.NetworkRssiInDecibelMilliwatts * -1); + double reverseMilliwatts = 100 - (network.AvailableNetwork.NetworkRssiInDecibelMilliwatts * -1); values[index - 2] = -1; values[index - 1] = reverseMilliwatts; @@ -497,30 +570,150 @@ private ChartValues SetChartValues(WiFiNetworkInfo network, WiFi.Radio r return values; } - private void AddNetworkToRadio1Chart(WiFiNetworkInfo network) + private LineSeries GetSeriesCollection(WiFiNetworkInfo network, WiFiRadio radio) { - int index = Array.IndexOf(Radio1Labels, $"{WiFi.GetChannelFromChannelFrequency(network.ChannelCenterFrequencyInKilohertz)}"); + int index = Array.IndexOf(radio == WiFiRadio.One ? Radio1Labels : Radio2Labels, $"{WiFi.GetChannelFromChannelFrequency(network.AvailableNetwork.ChannelCenterFrequencyInKilohertz)}"); - Radio1Series.Add(new LineSeries + return new LineSeries { - Title = network.SSID, - Values = SetChartValues(network, WiFi.Radio.One, index), + Title = $"{network.AvailableNetwork.Ssid} ({network.AvailableNetwork.Bssid})", + Values = GetChartValues(network, radio, index), PointGeometry = null, LineSmoothness = 0 - }); + }; } - private void AddNetworkToRadio2Chart(WiFiNetworkInfo network) + private async void Connect() { - int index = Array.IndexOf(Radio2Labels, $"{WiFi.GetChannelFromChannelFrequency(network.ChannelCenterFrequencyInKilohertz)}"); + var selectedAdapter = SelectedAdapter; + var selectedNetwork = SelectedNetwork; + + var connectMode = WiFi.GetConnectMode(selectedNetwork.AvailableNetwork); - Radio2Series.Add(new LineSeries + var customDialog = new CustomDialog { - Title = network.SSID, - Values = SetChartValues(network, WiFi.Radio.Two, index), - PointGeometry = null, - LineSmoothness = 0 - }); + Title = selectedNetwork.IsHidden ? Localization.Resources.Strings.HiddenNetwork : string.Format(Localization.Resources.Strings.ConnectToXXX, selectedNetwork.AvailableNetwork.Ssid) + }; + + var exportViewModel = new WiFiConnectViewModel(async instance => + { + // Connect Open/PSK/EAP + await _dialogCoordinator.HideMetroDialogAsync(this, customDialog); + + string ssid = selectedNetwork.IsHidden ? instance.Ssid : selectedNetwork.AvailableNetwork.Ssid; + + // Show status message + IsConnecting = true; + ConnectionStatusMessage = string.Format(Localization.Resources.Strings.ConnectingToXXX, ssid); + IsConnectionStatusMessageDisplayed = true; + + // Connect to the network + WiFiReconnectionKind reconnectionKind = instance.ConnectAutomatically ? WiFiReconnectionKind.Automatic : WiFiReconnectionKind.Manual; + + PasswordCredential credential = new(); + + switch (instance.ConnectMode) + { + case WiFiConnectMode.Psk: + credential.Password = SecureStringHelper.ConvertToString(instance.PreSharedKey); + break; + case WiFiConnectMode.Eap: + credential.UserName = instance.Username; + + if (!string.IsNullOrEmpty(instance.Domain)) + credential.Resource = instance.Domain; + + credential.Password = SecureStringHelper.ConvertToString(instance.Password); + break; + } + + WiFiConnectionStatus connectionResult; + + if (selectedNetwork.IsHidden) + connectionResult = await WiFi.ConnectAsync(instance.Options.AdapterInfo.WiFiAdapter, instance.Options.NetworkInfo.AvailableNetwork, reconnectionKind, credential, instance.Ssid); + else + connectionResult = await WiFi.ConnectAsync(instance.Options.AdapterInfo.WiFiAdapter, instance.Options.NetworkInfo.AvailableNetwork, reconnectionKind, credential); + + // Done connecting + IsConnecting = false; + + // Get result + if (connectionResult == WiFiConnectionStatus.Success) + ConnectionStatusMessage = string.Format(Localization.Resources.Strings.SuccessfullyConnectedToXXX, ssid); + else + ConnectionStatusMessage = string.Format(Localization.Resources.Strings.CouldNotConnectToXXXReasonXXX, ssid, WiFiConnectionStatusTranslator.GetInstance().Translate(connectionResult)); + + // Hide message automatically + _hideConnectionStatusMessageTimer.Start(); + + // Update the wifi networks. + // Wait because an error may occour if a refresh is done directly after connecting. + await Scan(SelectedAdapter, true, 5000); + + }, async instance => + { + // Connect WPS + await _dialogCoordinator.HideMetroDialogAsync(this, customDialog); + + string ssid = selectedNetwork.IsHidden ? instance.Ssid : selectedNetwork.AvailableNetwork.Ssid; + + // Show status message + IsConnecting = true; + ConnectionStatusMessage = string.Format(Localization.Resources.Strings.ConnectingToXXX, ssid); + IsConnectionStatusMessageDisplayed = true; + + // Connect to the network + WiFiReconnectionKind reconnectionKind = instance.ConnectAutomatically ? WiFiReconnectionKind.Automatic : WiFiReconnectionKind.Manual; + + WiFiConnectionStatus connectionResult = await WiFi.ConnectWpsAsync(instance.Options.AdapterInfo.WiFiAdapter, instance.Options.NetworkInfo.AvailableNetwork, reconnectionKind); + + // Done connecting + IsConnecting = false; + + // Get result + if (connectionResult == WiFiConnectionStatus.Success) + ConnectionStatusMessage = string.Format(Localization.Resources.Strings.SuccessfullyConnectedToXXX, ssid); + else + ConnectionStatusMessage = string.Format(Localization.Resources.Strings.CouldNotConnectToXXXReasonXXX, ssid, WiFiConnectionStatusTranslator.GetInstance().Translate(connectionResult)); + + // Hide message automatically + _hideConnectionStatusMessageTimer.Start(); + + // Update the wifi networks. + // Wait because an error may occour if a refresh is done directly after connecting. + await Scan(SelectedAdapter, true, 5000); + }, + + instance => + { + _dialogCoordinator.HideMetroDialogAsync(this, customDialog); + }, (selectedAdapter, selectedNetwork), connectMode); + + customDialog.Content = new WiFiConnectDialog + { + DataContext = exportViewModel + }; + + await _dialogCoordinator.ShowMetroDialogAsync(this, customDialog); + } + + private async void Disconnect() + { + var connectedNetwork = Networks.FirstOrDefault(x => x.IsConnected); + + WiFi.Disconnect(SelectedAdapter.WiFiAdapter); + + if (connectedNetwork != null) + { + ConnectionStatusMessage = string.Format(Localization.Resources.Strings.XXXDisconnected, connectedNetwork.AvailableNetwork.Ssid); + IsConnectionStatusMessageDisplayed = true; + + // Hide message automatically + _hideConnectionStatusMessageTimer.Start(); + } + + // Refresh + await Scan(SelectedAdapter, true, 2500); } private async Task Export() @@ -548,7 +741,10 @@ private async Task Export() SettingsManager.Current.WiFi_ExportFileType = instance.FileType; SettingsManager.Current.WiFi_ExportFilePath = instance.FilePath; - }, instance => { _dialogCoordinator.HideMetroDialogAsync(this, customDialog); }, new ExportFileType[] { ExportFileType.CSV, ExportFileType.XML, ExportFileType.JSON }, true, SettingsManager.Current.WiFi_ExportFileType, SettingsManager.Current.WiFi_ExportFilePath); + }, instance => + { + _dialogCoordinator.HideMetroDialogAsync(this, customDialog); + }, new ExportFileType[] { ExportFileType.CSV, ExportFileType.XML, ExportFileType.JSON }, true, SettingsManager.Current.WiFi_ExportFileType, SettingsManager.Current.WiFi_ExportFilePath); customDialog.Content = new ExportDialog { @@ -571,20 +767,29 @@ public void OnViewHide() if (AutoRefreshEnabled) _autoRefreshTimer.Stop(); } - #endregion #region Events private async void AutoRefreshTimer_Tick(object sender, EventArgs e) { + // Don't refresh if it's already loading or connecting + if (IsNetworksLoading || IsBackgroundSearchRunning || IsConnecting) + return; + // Stop timer... _autoRefreshTimer.Stop(); // Scan networks - await Scan(SelectedAdapter.WiFiAdapter, true); + await Scan(SelectedAdapter, true); // Restart timer... _autoRefreshTimer.Start(); } + + private void HideConnectionStatusMessageTimer_Tick(object sender, EventArgs e) + { + _hideConnectionStatusMessageTimer.Stop(); + IsConnectionStatusMessageDisplayed = false; + } #endregion } diff --git a/Source/NETworkManager/Views/ARPTableAddEntryDialog.xaml b/Source/NETworkManager/Views/ARPTableAddEntryDialog.xaml index 33e0298ee1..4a37ee07cf 100644 --- a/Source/NETworkManager/Views/ARPTableAddEntryDialog.xaml +++ b/Source/NETworkManager/Views/ARPTableAddEntryDialog.xaml @@ -3,7 +3,7 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" - xmlns:mahAppsControls="http://metro.mahapps.com/winfx/xaml/controls" + xmlns:mah="http://metro.mahapps.com/winfx/xaml/controls" xmlns:validators="clr-namespace:NETworkManager.Validators;assembly=NETworkManager.Validators" xmlns:viewModels="clr-namespace:NETworkManager.ViewModels" xmlns:localization="clr-namespace:NETworkManager.Localization.Resources;assembly=NETworkManager.Localization" @@ -30,7 +30,7 @@ - + @@ -41,7 +41,7 @@ - + diff --git a/Source/NETworkManager/Views/WiFiConnectDialog.xaml b/Source/NETworkManager/Views/WiFiConnectDialog.xaml new file mode 100644 index 0000000000..fd111dd5a6 --- /dev/null +++ b/Source/NETworkManager/Views/WiFiConnectDialog.xaml @@ -0,0 +1,231 @@ + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + - - - - - - - - - + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/Changelog/next-release.md b/docs/Changelog/next-release.md index a3ffa5ba11..1de037df74 100644 --- a/docs/Changelog/next-release.md +++ b/docs/Changelog/next-release.md @@ -16,13 +16,19 @@ Release date: **xx.xx.2023** - [.NET Desktop Runtime 6.x (LTS)](https://dotnet.microsoft.com/download/dotnet/6.0){:target="\_blank"} ## What's new? +- WiFi + - Connect to a WiFi network has been added. Supported networks / methods are `Open`, `WPS`, `WPA PSK (Pre-shared key)` and `WPA Enterprise`. To do this, right-click on a selected WiFi network to open the ContextMenu and select `Connect...`. [#2133](https://github.com/BornToBeRoot/NETworkManager/pull/2133){:target="\_blank"} + - Disconnect from a WiFi network has been added. To do this, right-click on the connected WiFi network to open the ContextMenu and select `Disconnect`. [#2133](https://github.com/BornToBeRoot/NETworkManager/pull/2133){:target="\_blank"} - Remote Desktop - - Support for Remote Desktop Gateway server added [#2108](https://github.com/BornToBeRoot/NETworkManager/pull/2108){:target="\_blank"} + - Support for Remote Desktop Gateway server has been added [#2108](https://github.com/BornToBeRoot/NETworkManager/pull/2108){:target="\_blank"} - SNMP - - Cancel is now supported by the underlying library [#2124](https://github.com/BornToBeRoot/NETworkManager/pull/2124){:target="\_blank"} - + - SNMP query can now be canceled (It's supported by the library now) [#2124](https://github.com/BornToBeRoot/NETworkManager/pull/2124){:target="\_blank"} + ## Improvements - WiFi + - Show current connected network [#2133](https://github.com/BornToBeRoot/NETworkManager/pull/2133){:target="\_blank"} + - Bssid to channel ToolTip added [#2133](https://github.com/BornToBeRoot/NETworkManager/pull/2133){:target="\_blank"} + - Show error message if scan fails (e.g. wifi adapter is unplugged while scanning) [#2133](https://github.com/BornToBeRoot/NETworkManager/pull/2133){:target="\_blank"} - Automatically refresh is now enabled if it was enabled on the last exit [#2116](https://github.com/BornToBeRoot/NETworkManager/pull/2116){:target="\_blank"} - Remote Desktop - Domain added to credentials [#2108](https://github.com/BornToBeRoot/NETworkManager/pull/2108){:target="\_blank"} @@ -32,14 +38,18 @@ Release date: **xx.xx.2023** - Automatically refresh is now enabled if it was enabled on the last exit [#2116](https://github.com/BornToBeRoot/NETworkManager/pull/2116){:target="\_blank"} - ARP Table - Automatically refresh is now enabled if it was enabled on the last exit [#2116](https://github.com/BornToBeRoot/NETworkManager/pull/2116){:target="\_blank"} +- Status window is now automatically closed again if it was opened by a network change event [#2105](https://github.com/BornToBeRoot/NETworkManager/pull/2105){:target="\_blank"} ## Bugfixes -- Status window is now automatically closed again if it was opened by a network change event [#2105](https://github.com/BornToBeRoot/NETworkManager/pull/2105){:target="\_blank"} +- Profiles + - OK button not disabled initially on unlock profile & decrypt profile file [#2133](https://github.com/BornToBeRoot/NETworkManager/pull/2133){:target="\_blank"} ## Other - Code cleanup [#2100](https://github.com/BornToBeRoot/NETworkManager/pull/2100){:target="\_blank"} - Language files updated [#transifex](https://github.com/BornToBeRoot/NETworkManager/pulls?q=author%3Aapp%2Ftransifex-integration){:target="\_blank"} - Dependencies updated [#dependencies](https://github.com/BornToBeRoot/NETworkManager/pulls?q=author%3Aapp%2Fdependabot){:target="\_blank"} +- Update documentation for: + - Application > WiFi [#2133](https://github.com/BornToBeRoot/NETworkManager/pull/2133){:target="\_blank"} - Add documentation for: - Application > Lookup [#2112](https://github.com/BornToBeRoot/NETworkManager/pull/2112){:target="\_blank"} - Application > Connections [#2109](https://github.com/BornToBeRoot/NETworkManager/pull/2109){:target="\_blank"} diff --git a/docs/Documentation/01_Application/03_WiFi.md b/docs/Documentation/01_Application/03_WiFi.md index 94278c6eff..85199726ab 100644 --- a/docs/Documentation/01_Application/03_WiFi.md +++ b/docs/Documentation/01_Application/03_WiFi.md @@ -18,6 +18,11 @@ Hidden wireless networks are displayed as `Hidden Network`. On the **WiFi** tab, you can select which wireless network adapter is used to scan for wireless networks. Wireless networks can be filtered by 2.4 Ghz, 5 Ghz and the SSID. +Right-clicking on a wireless network opens a context menu with the following options: +- **Connect...**: Opens a dialog to connect to the selected wireless network. +- **Disconnect**: Disconnect from the selected wireless network. +- **Export...**: Opens a dialog to export the selected or all wireless network(s) to a file. + In the search field, you can filter the wireless networks by `SSID`, `Security`, `Channel`, `MAC Address (BSSID)`, `Vendor` and `Phy kind`. The search is case insensitive. {: .note }