diff --git a/README.md b/README.md index 5bbffe5..3a5e090 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ WLAN Profile Viewer is a Windows desktop app to manage wireless LAN profiles. It ##Download -[Download](https://github.com/emoacht/WlanProfileViewer/releases/download/1.0.0/WlanProfileViewer100.zip) +[Download](https://github.com/emoacht/WlanProfileViewer/releases/download/1.1.0/WlanProfileViewer110.zip) ##Install @@ -50,11 +50,13 @@ Settings file will be saved in the following folder.
- [Reactive Extensions][1] - [Reactive Property][2] - - [WPF Monitor Aware Window][3] + - [Managed Native Wifi][3] + - [WPF Monitor Aware Window][4] [1]: https://github.com/Reactive-Extensions/Rx.NET [2]: https://github.com/runceel/ReactiveProperty -[3]: https://github.com/emoacht/WpfMonitorAware +[3]: https://github.com/emoacht/ManagedNativeWifi +[4]: https://github.com/emoacht/WpfMonitorAware ##Reference diff --git a/README_ja.md b/README_ja.md index 53f65be..3bf4ce1 100644 --- a/README_ja.md +++ b/README_ja.md @@ -19,7 +19,7 @@ WLAN Profile Viewerは無線LANプロファイルを管理するためのWindows ##ダウンロード -[ダウンロード](https://github.com/emoacht/WlanProfileViewer/releases/download/1.0.0/WlanProfileViewer100.zip) +[ダウンロード](https://github.com/emoacht/WlanProfileViewer/releases/download/1.1.0/WlanProfileViewer110.zip) ##インストール @@ -50,11 +50,13 @@ WLAN Profile Viewerは無線LANプロファイルを管理するためのWindows - [Reactive Extensions][1] - [Reactive Property][2] - - [WPF Monitor Aware Window][3] + - [Managed Native Wifi][3] + - [WPF Monitor Aware Window][4] [1]: https://github.com/Reactive-Extensions/Rx.NET [2]: https://github.com/runceel/ReactiveProperty -[3]: https://github.com/emoacht/WpfMonitorAware +[3]: https://github.com/emoacht/ManagedNativeWifi +[4]: https://github.com/emoacht/WpfMonitorAware ##参考 diff --git a/ReactivePropertyTest/ReactivePropertyTest.csproj b/ReactivePropertyTest/ReactivePropertyTest.csproj index 3bdd370..cb27431 100644 --- a/ReactivePropertyTest/ReactivePropertyTest.csproj +++ b/ReactivePropertyTest/ReactivePropertyTest.csproj @@ -36,15 +36,15 @@ - ..\packages\ReactiveProperty.2.2.3.1\lib\net45\ReactiveProperty.dll + ..\packages\ReactiveProperty.2.2.8\lib\net45\ReactiveProperty.dll True - ..\packages\ReactiveProperty.2.2.3.1\lib\net45\ReactiveProperty.DataAnnotations.dll + ..\packages\ReactiveProperty.2.2.8\lib\net45\ReactiveProperty.DataAnnotations.dll True - ..\packages\ReactiveProperty.2.2.3.1\lib\net45\ReactiveProperty.NET45.dll + ..\packages\ReactiveProperty.2.2.8\lib\net45\ReactiveProperty.NET45.dll True diff --git a/ReactivePropertyTest/packages.config b/ReactivePropertyTest/packages.config index 99ac362..88a6a63 100644 --- a/ReactivePropertyTest/packages.config +++ b/ReactivePropertyTest/packages.config @@ -1,6 +1,6 @@  - + diff --git a/WlanProfileViewer/Library/ManagedNativeWifi.dll b/WlanProfileViewer/Library/ManagedNativeWifi.dll new file mode 100644 index 0000000..61b47de Binary files /dev/null and b/WlanProfileViewer/Library/ManagedNativeWifi.dll differ diff --git a/WlanProfileViewer/Library/ManagedNativeWifi.xml b/WlanProfileViewer/Library/ManagedNativeWifi.xml new file mode 100644 index 0000000..781200e --- /dev/null +++ b/WlanProfileViewer/Library/ManagedNativeWifi.xml @@ -0,0 +1,544 @@ + + + + ManagedNativeWifi + + + + + BSS network type + + + + + None + + + + + Infrastructure BSS network + + + + + Independent BSS (IBSS) network (Ad hoc network) + + + + + Any BSS network + + + + + Wireless interface information + + + + + Interface ID + + + + + Interface description + + + + + Interface state + + + + + Constructor + + + + + Wireless interface state + + Equivalent to WLAN_INTERFACE_STATE + + + + The interface is not ready to operate. + + + + + The interface is connected to a network. + + + + + The interface is the first node in an ad hoc network. No peer has connected. + + + + + The interface is disconnecting from the current network. + + + + + The interface is not connected to any network. + + + + + The interface is attempting to associate with a network. + + + + + Auto configuration is discovering the settings for the network. + + + + + The interface is in the process of authenticating. + + + + + A managed implementation of Native Wifi API + + + + + Enumerate wireless interface information. + + Wireless interface information + + + + Asynchronously request wireless interfaces to scan (rescan) wireless LANs. + + Timeout duration + Interface IDs that successfully scanned + + + + Asynchronously request wireless interfaces to scan (rescan) wireless LANs. + + Timeout duration + Cancellation token + Interface IDs that successfully scanned + + + + Enumerate SSIDs of available wireless LANs. + + SSIDs + + + + Enumerate SSIDs of connected wireless LANs. + + SSIDs + + + + Enumerate wireless LAN information on available networks. + + Wireless LAN information + If multiple profiles are associated with a same network, there will be multiple + entries with the same SSID. + + + + Enumerate wireless LAN information on BSS networks. + + Wireless LAN information + + + + Enumerate wireless profile names in preference order. + + Wireless profile names + + + + Enumerate wireless profile information in preference order. + + Wireless profile information + + + + Get a specified wireless profile information. + + Client handle + Interface information + Profile name + Signal quality + Position in preference order + Whether this profile is connected to a wireless LAN + Wireless profile information + + For profile elements, see + https://msdn.microsoft.com/en-us/library/windows/desktop/ms707381.aspx + + + + + Set (add or overwrite) the content of a specific profile. + + Interface ID + Profile type + Profile XML + Security descriptor for all-user profile + Whether to overwrite an existing profile + True if successfully set. False if not. + + If the content of the profile XML is not valid, a Win32Exception will be thrown. + In such case, check the reason code in the message and see + https://msdn.microsoft.com/en-us/library/windows/desktop/ms707394.aspx + https://technet.microsoft.com/en-us/library/3ed3d027-5ae8-4cb0-ade5-0a7c446cd4f7#BKMK_AppndxE + + + + + Set the position of a specified wireless profile in preference order. + + Interface ID + Profile name + Position (starting from 0) + True if successfully set. + + + + Delete a specified wireless profile. + + Interface ID + Profile name + True if successfully deleted. False if could not delete. + + + + Attempt to connect to the wireless LAN associated to a specified wireless profile. + + Interface ID + Profile name + BSS network type + True if successfully requested the connection. False if failed. + + + + Asynchronously attempt to connect to the wireless LAN associated to a specified wireless profile. + + Interface ID + Profile name + BSS network type + Timeout duration + True if successfully connected. False if failed or timed out. + + + + Asynchronously attempt to connect to the wireless LAN associated to a specified wireless profile. + + Interface ID + Profile name + BSS network type + Timeout duration + Cancellation token + True if successfully connected. False if failed or timed out. + + + + Disconnect from the wireless LAN associated to a specified wireless interface. + + Interface ID + True if successfully requested the disconnection. False if failed. + + + + Asynchronously disconnect from the wireless LAN associated to a specified wireless interface. + + Interface ID + Timeout duration + True if successfully disconnected. False if failed or timed out. + + + + Asynchronously disconnect from the wireless LAN associated to a specified wireless interface. + + Interface ID + Timeout duration + Cancellation token + True if successfully disconnected. False if failed or timed out. + + + + Detect wireless LAN channel from center frequency. + + Center frequency (KHz) + If successfully detected, channel number. If not, 0. + + This method is marked as internal for unit test. + As for 5GHz, this method may produce a channel number which is not actually in use. + Also, some channel numbers of 5GHz overlap those of 3.6GHz. In such cases, refer + the frequency to distinguish them. + + + + + Wireless LAN information + + + + + Associated wireless interface information + + + + + SSID (maximum 32 bytes) + + + + + BSS network type + + + + + Signal quality (0-100) + + + + + Whether security is enabled on this network + + + + + Associated wireless profile name + + + + + Constructor + + + + + Wireless LAN information + + + + + Associated wireless interface information + + + + + SSID (maximum 32 bytes) + + + + + BSS network type + + + + + BSSID (6 bytes) + + + + + Signal strength (RSSI) + + + + + Link quality (0-100) + + + + + Wireless LAN frequency (KHz) + + + + + Wireless LAN channel + + + + + Constructor + + + + + Identifier of wireless LAN + + This class is immutable. + + + + Constructor + + + + + Return the identifier in byte array. + + Identifier in byte array + + + + Return the identifier in UTF-8 string. + + Identifier in UTF-8 string + + + + Wireless profile information + + + + + Profile name + + + + + Associated wireless interface information + + + + + Profile type + + + + + Profile XML + + + + + SSID of associated wireless LAN + + + + + BSS network type of associated wireless LAN + + + + + Authentication type of associated wireless LAN + + + + + Encryption type of associated wireless LAN + + + + + Signal quality of associated wireless LAN + + + + + Position in preference order of associated wireless interface + + + + + Whether this profile is set to be automatically connected + + + + + Whether this profile is currently connected + + + + + Constructor + + + + + Wireless profile type + + + + + All-user profile + + + + + Group policy profile + + Equivalent to WLAN_PROFILE_GROUP_POLICY + + + + Per-user profile + + Equivalent to WLAN_PROFILE_USER + + + + Return the byte array of SSID. + + Byte array + + + + Return the UTF-8 string representation of SSID + + If successfully converted the byte array of SSID, UTF-8 string. If not, null. + + + + Return the byte array of MAC address + + + + + + Return the hexadecimal string representation of MAC address delimited by colon. + + Hexadecimal string + + + + Infrastructure BSS network + + + + + Independent BSS (IBSS) network + + + + + Either infrastructure or IBSS network + + + + + Wrapper class only for handle taken by WlanOpenHandle function in Native Wifi API + + + This implementation is based on: + http://referencesource.microsoft.com/#mscorlib/system/runtime/interopservices/safehandle.cs + + + + + Default constructor + + This constructor is for P/Invoke. + + + diff --git a/WlanProfileViewer/Models/Operation.cs b/WlanProfileViewer/Models/Operation.cs index 4816db3..69c8292 100644 --- a/WlanProfileViewer/Models/Operation.cs +++ b/WlanProfileViewer/Models/Operation.cs @@ -52,6 +52,9 @@ public bool IsSuspended private ReactiveTimer ReloadTimer { get; } + public Operation() : this(new NativeWifiWorker()) + { } + public Operation(IWlanWorker worker) { this._worker = worker; @@ -154,7 +157,7 @@ public async Task LoadProfilesAsync(bool isLatest) // Calculate count of positions for each interface. Profiles - .GroupBy(x => x.InterfaceGuid) + .GroupBy(x => x.InterfaceId) .ToList() .ForEach(profilesGroup => { @@ -239,21 +242,21 @@ public async Task DeleteProfileAsync() x => !Profiles.Contains(x)); } - public async Task ConnectAsync() + public async Task ConnectNetworkAsync() { Debug.WriteLine("Connect start!"); return await WorkAsync( - x => _worker.ConnectAsync(x, _workingTimeoutDuration), + x => _worker.ConnectNetworkAsync(x, _workingTimeoutDuration), x => Profiles.Contains(x) && x.IsConnected); } - public async Task DisconnectAsync() + public async Task DisconnectNetworkAsync() { Debug.WriteLine("Disconnect start!"); return await WorkAsync( - x => _worker.DisconnectAsync(x, _workingTimeoutDuration), + x => _worker.DisconnectNetworkAsync(x, _workingTimeoutDuration), x => Profiles.Contains(x) && !x.IsConnected); } diff --git a/WlanProfileViewer/Models/Wlan/AuthenticationMethod.cs b/WlanProfileViewer/Models/Wlan/AuthenticationMethod.cs index afce33a..fb5ec2f 100644 --- a/WlanProfileViewer/Models/Wlan/AuthenticationMethod.cs +++ b/WlanProfileViewer/Models/Wlan/AuthenticationMethod.cs @@ -24,25 +24,25 @@ public enum AuthenticationMethod /// /// WPA-Enterprise 802.11 authentication /// - /// WPA in profile xml + /// WPA in profile XML WPA_Enterprise, /// /// WPA-Personal 802.11 authentication /// - /// WPAPSK in profile xml + /// WPAPSK in profile XML WPA_Personal, /// /// WPA2-Enterprise 802.11 authentication /// - /// WPA2 in profile xml + /// WPA2 in profile XML WPA2_Enterprise, /// /// WPA2-Personal 802.11 authentication /// - /// WPA2PSK in profile xml + /// WPA2PSK in profile XML WPA2_Personal } } \ No newline at end of file diff --git a/WlanProfileViewer/Models/Wlan/IWlanWorker.cs b/WlanProfileViewer/Models/Wlan/IWlanWorker.cs index 8564999..74db691 100644 --- a/WlanProfileViewer/Models/Wlan/IWlanWorker.cs +++ b/WlanProfileViewer/Models/Wlan/IWlanWorker.cs @@ -8,12 +8,12 @@ namespace WlanProfileViewer.Models.Wlan { internal interface IWlanWorker { - Task> GetProfilesAsync(bool isLatest, TimeSpan timeoutDuration); + Task> GetProfilesAsync(bool isLatest, TimeSpan timeout); Task SetProfilePositionAsync(ProfileItem profileItem, int position); Task DeleteProfileAsync(ProfileItem profileItem); - Task ConnectAsync(ProfileItem profileItem, TimeSpan timeoutDuration); - Task DisconnectAsync(ProfileItem profileItem, TimeSpan timeoutDuration); + Task ConnectNetworkAsync(ProfileItem profileItem, TimeSpan timeout); + Task DisconnectNetworkAsync(ProfileItem profileItem, TimeSpan timeout); } } \ No newline at end of file diff --git a/WlanProfileViewer/Models/Wlan/MockWorker.cs b/WlanProfileViewer/Models/Wlan/MockWorker.cs index 72b48a6..1d1fa22 100644 --- a/WlanProfileViewer/Models/Wlan/MockWorker.cs +++ b/WlanProfileViewer/Models/Wlan/MockWorker.cs @@ -12,7 +12,7 @@ internal class MockWorker : IWlanWorker private List _sourceProfiles; private readonly Random _random = new Random(); - public async Task> GetProfilesAsync(bool isLatest, TimeSpan timeoutDuration) + public async Task> GetProfilesAsync(bool isLatest, TimeSpan timeout) { if (_sourceProfiles == null) _sourceProfiles = PopulateProfiles().ToList(); @@ -34,7 +34,7 @@ public async Task SetProfilePositionAsync(ProfileItem profileItem, int pos await WaitAsync(); var targetProfiles = _sourceProfiles - .Where(x => x.InterfaceGuid == profileItem.InterfaceGuid) + .Where(x => x.InterfaceId == profileItem.InterfaceId) .OrderBy(x => x.Position) .ToList(); @@ -64,7 +64,7 @@ public async Task DeleteProfileAsync(ProfileItem profileItem) return _sourceProfiles.Remove(profileItem); } - public async Task ConnectAsync(ProfileItem profileItem, TimeSpan timeoutDuration) + public async Task ConnectNetworkAsync(ProfileItem profileItem, TimeSpan timeout) { await WaitAsync(); @@ -76,7 +76,7 @@ public async Task ConnectAsync(ProfileItem profileItem, TimeSpan timeoutDu return true; } - public async Task DisconnectAsync(ProfileItem profileItem, TimeSpan timeoutDuration) + public async Task DisconnectNetworkAsync(ProfileItem profileItem, TimeSpan timeout) { await WaitAsync(); @@ -108,7 +108,7 @@ private IEnumerable PopulateProfiles() { new ProfileItem( name: "at_STATION_Wi2", - interfaceGuid: interfaceGuid0, + interfaceId: interfaceGuid0, interfaceName: interfaceName0, interfaceDescription: interfaceDescription0, authentication: AuthenticationMethod.Open, @@ -120,7 +120,7 @@ private IEnumerable PopulateProfiles() new ProfileItem( name: "MSFTOPEN", - interfaceGuid: interfaceGuid0, + interfaceId: interfaceGuid0, interfaceName: interfaceName0, interfaceDescription: interfaceDescription0, authentication: AuthenticationMethod.Open, @@ -132,7 +132,7 @@ private IEnumerable PopulateProfiles() new ProfileItem( name: "flashair_W02", - interfaceGuid: interfaceGuid0, + interfaceId: interfaceGuid0, interfaceName: interfaceName0, interfaceDescription: interfaceDescription0, authentication: AuthenticationMethod.WPA2_Personal, @@ -144,7 +144,7 @@ private IEnumerable PopulateProfiles() new ProfileItem( name: "flashair_W03", - interfaceGuid: interfaceGuid0, + interfaceId: interfaceGuid0, interfaceName: interfaceName0, interfaceDescription: interfaceDescription0, authentication: AuthenticationMethod.WPA2_Personal, @@ -156,7 +156,7 @@ private IEnumerable PopulateProfiles() new ProfileItem( name: "WIFIGATE-968", - interfaceGuid: interfaceGuid0, + interfaceId: interfaceGuid0, interfaceName: interfaceName0, interfaceDescription: interfaceDescription0, authentication: AuthenticationMethod.WPA2_Personal, @@ -168,7 +168,7 @@ private IEnumerable PopulateProfiles() new ProfileItem( name: "at_STATION_Wi2", - interfaceGuid: interfaceGuid1, + interfaceId: interfaceGuid1, interfaceName: interfaceName1, interfaceDescription: interfaceDescription1, authentication: AuthenticationMethod.Open, @@ -180,7 +180,7 @@ private IEnumerable PopulateProfiles() new ProfileItem( name: "ねこラン🐾🐾", - interfaceGuid: interfaceGuid1, + interfaceId: interfaceGuid1, interfaceName: interfaceName1, interfaceDescription: interfaceDescription1, authentication: AuthenticationMethod.WPA_Personal, @@ -192,7 +192,7 @@ private IEnumerable PopulateProfiles() new ProfileItem( name: "ZZZZZ...", - interfaceGuid: interfaceGuid2, + interfaceId: interfaceGuid2, interfaceName: interfaceName2, interfaceDescription: interfaceDescription2, authentication: AuthenticationMethod.Open, diff --git a/WlanProfileViewer/Models/Wlan/NativeWifi.cs b/WlanProfileViewer/Models/Wlan/NativeWifi.cs deleted file mode 100644 index a841639..0000000 --- a/WlanProfileViewer/Models/Wlan/NativeWifi.cs +++ /dev/null @@ -1,1454 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; -using System.Xml.Linq; - -namespace WlanProfileViewer.Models.Wlan -{ - /// - /// A managed implementation of Native Wifi API - /// - internal class NativeWifi - { - #region Win32 - - [DllImport("Wlanapi.dll", SetLastError = true)] - private static extern uint WlanOpenHandle( - uint dwClientVersion, - IntPtr pReserved, - out uint pdwNegotiatedVersion, - out IntPtr phClientHandle); - - [DllImport("Wlanapi.dll", SetLastError = true)] - private static extern uint WlanCloseHandle( - IntPtr hClientHandle, - IntPtr pReserved); - - [DllImport("Wlanapi.dll", SetLastError = true)] - private static extern void WlanFreeMemory(IntPtr pMemory); - - [DllImport("Wlanapi.dll", SetLastError = true)] - private static extern uint WlanEnumInterfaces( - IntPtr hClientHandle, - IntPtr pReserved, - out IntPtr ppInterfaceList); - - [DllImport("Wlanapi.dll", SetLastError = true)] - private static extern uint WlanScan( - IntPtr hClientHandle, - [MarshalAs(UnmanagedType.LPStruct)] Guid pInterfaceGuid, - IntPtr pDot11Ssid, - IntPtr pIeData, - IntPtr pReserved); - - [DllImport("Wlanapi.dll", SetLastError = true)] - private static extern uint WlanGetAvailableNetworkList( - IntPtr hClientHandle, - [MarshalAs(UnmanagedType.LPStruct)] Guid pInterfaceGuid, - uint dwFlags, - IntPtr pReserved, - out IntPtr ppAvailableNetworkList); - - [DllImport("Wlanapi.dll", SetLastError = true)] - private static extern uint WlanQueryInterface( - IntPtr hClientHandle, - [MarshalAs(UnmanagedType.LPStruct)] Guid pInterfaceGuid, - WLAN_INTF_OPCODE OpCode, - IntPtr pReserved, - out uint pdwDataSize, - ref IntPtr ppData, - IntPtr pWlanOpcodeValueType); - - [DllImport("Wlanapi.dll", SetLastError = true)] - private static extern uint WlanGetProfileList( - IntPtr hClientHandle, - [MarshalAs(UnmanagedType.LPStruct)] Guid pInterfaceGuid, - IntPtr pReserved, - out IntPtr ppProfileList); - - [DllImport("Wlanapi.dll", SetLastError = true)] - private static extern uint WlanGetProfile( - IntPtr hClientHandle, - [MarshalAs(UnmanagedType.LPStruct)] Guid pInterfaceGuid, - [MarshalAs(UnmanagedType.LPWStr)] string strProfileName, - IntPtr pReserved, - out IntPtr pstrProfileXml, - ref uint pdwFlags, - out uint pdwGrantedAccess); - - [DllImport("Wlanapi.dll", SetLastError = true)] - private static extern uint WlanSetProfilePosition( - IntPtr hClientHandle, - [MarshalAs(UnmanagedType.LPStruct)] Guid pInterfaceGuid, - [MarshalAs(UnmanagedType.LPWStr)] string strProfileName, - uint dwPosition, - IntPtr pReserved); - - [DllImport("Wlanapi.dll", SetLastError = true)] - private static extern uint WlanDeleteProfile( - IntPtr hClientHandle, - [MarshalAs(UnmanagedType.LPStruct)] Guid pInterfaceGuid, - [MarshalAs(UnmanagedType.LPWStr)] string strProfileName, - IntPtr pReserved); - - [DllImport("Wlanapi.dll", SetLastError = true)] - private static extern uint WlanConnect( - IntPtr hClientHandle, - [MarshalAs(UnmanagedType.LPStruct)] Guid pInterfaceGuid, - [In] ref WLAN_CONNECTION_PARAMETERS pConnectionParameters, - IntPtr pReserved); - - [DllImport("Wlanapi.dll", SetLastError = true)] - private static extern uint WlanDisconnect( - IntPtr hClientHandle, - [MarshalAs(UnmanagedType.LPStruct)] Guid pInterfaceGuid, - IntPtr pReserved); - - [DllImport("Wlanapi.dll", SetLastError = true)] - private static extern uint WlanRegisterNotification( - IntPtr hClientHandle, - uint dwNotifSource, - [MarshalAs(UnmanagedType.Bool)] bool bIgnoreDuplicate, - WLAN_NOTIFICATION_CALLBACK funcCallback, - IntPtr pCallbackContext, - IntPtr pReserved, - uint pdwPrevNotifSource); - - private delegate void WLAN_NOTIFICATION_CALLBACK( - IntPtr data, // Pointer to WLAN_NOTIFICATION_DATA - IntPtr context); - - [DllImport("Kernel32.dll", SetLastError = true)] - private static extern uint FormatMessage( - uint dwFlags, - IntPtr lpSource, - uint dwMessageId, - uint dwLanguageId, - StringBuilder lpBuffer, - int nSize, - IntPtr Arguments); - - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] - private struct WLAN_INTERFACE_INFO - { - public Guid InterfaceGuid; - - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] - public string strInterfaceDescription; - - public WLAN_INTERFACE_STATE isState; - } - - [StructLayout(LayoutKind.Sequential)] - private struct WLAN_INTERFACE_INFO_LIST - { - public uint dwNumberOfItems; - public uint dwIndex; - public WLAN_INTERFACE_INFO[] InterfaceInfo; - - public WLAN_INTERFACE_INFO_LIST(IntPtr ppInterfaceList) - { - dwNumberOfItems = (uint)Marshal.ReadInt32(ppInterfaceList, 0); - dwIndex = (uint)Marshal.ReadInt32(ppInterfaceList, 4); - InterfaceInfo = new WLAN_INTERFACE_INFO[dwNumberOfItems]; - - var offset = Marshal.SizeOf(typeof(uint)) * 2; // Size of dwNumberOfItems and dwIndex - - for (int i = 0; i < dwNumberOfItems; i++) - { - var interfaceInfo = new IntPtr(ppInterfaceList.ToInt64() + (Marshal.SizeOf(typeof(WLAN_INTERFACE_INFO)) * i) + offset); - InterfaceInfo[i] = Marshal.PtrToStructure(interfaceInfo); - } - } - } - - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] - private struct WLAN_AVAILABLE_NETWORK - { - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] - public string strProfileName; - - public DOT11_SSID dot11Ssid; - public DOT11_BSS_TYPE dot11BssType; - public uint uNumberOfBssids; - public bool bNetworkConnectable; - public uint wlanNotConnectableReason; - public uint uNumberOfPhyTypes; - - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] - public DOT11_PHY_TYPE[] dot11PhyTypes; - - public bool bMorePhyTypes; - public uint wlanSignalQuality; - public bool bSecurityEnabled; - public DOT11_AUTH_ALGORITHM dot11DefaultAuthAlgorithm; - public DOT11_CIPHER_ALGORITHM dot11DefaultCipherAlgorithm; - public uint dwFlags; - public uint dwReserved; - } - - [StructLayout(LayoutKind.Sequential)] - private struct WLAN_AVAILABLE_NETWORK_LIST - { - public uint dwNumberOfItems; - public uint dwIndex; - public WLAN_AVAILABLE_NETWORK[] Network; - - public WLAN_AVAILABLE_NETWORK_LIST(IntPtr ppAvailableNetworkList) - { - dwNumberOfItems = (uint)Marshal.ReadInt32(ppAvailableNetworkList, 0); - dwIndex = (uint)Marshal.ReadInt32(ppAvailableNetworkList, 4); - Network = new WLAN_AVAILABLE_NETWORK[dwNumberOfItems]; - - var offset = Marshal.SizeOf(typeof(uint)) * 2; // Size of dwNumberOfItems and dwIndex - - for (int i = 0; i < dwNumberOfItems; i++) - { - var availableNetwork = new IntPtr(ppAvailableNetworkList.ToInt64() + (Marshal.SizeOf(typeof(WLAN_AVAILABLE_NETWORK)) * i) + offset); - Network[i] = Marshal.PtrToStructure(availableNetwork); - } - } - } - - [StructLayout(LayoutKind.Sequential)] - private struct DOT11_SSID - { - public uint uSSIDLength; - - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] - public byte[] ucSSID; - - public byte[] ToSsidBytes() - { - return (ucSSID != null) - ? ucSSID.Take((int)uSSIDLength).ToArray() - : null; - } - - public string ToSsidString() - { - return (ucSSID != null) - ? Encoding.UTF8.GetString(ToSsidBytes()) - : null; - } - } - - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] - private struct WLAN_CONNECTION_ATTRIBUTES - { - public WLAN_INTERFACE_STATE isState; - public WLAN_CONNECTION_MODE wlanConnectionMode; - - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] - public string strProfileName; - - public WLAN_ASSOCIATION_ATTRIBUTES wlanAssociationAttributes; - public WLAN_SECURITY_ATTRIBUTES wlanSecurityAttributes; - } - - [StructLayout(LayoutKind.Sequential)] - private struct WLAN_ASSOCIATION_ATTRIBUTES - { - public DOT11_SSID dot11Ssid; - public DOT11_BSS_TYPE dot11BssType; - - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] - public byte[] dot11Bssid; // DOT11_MAC_ADDRESS - - public DOT11_PHY_TYPE dot11PhyType; - public uint uDot11PhyIndex; - public uint wlanSignalQuality; - public uint ulRxRate; - public uint ulTxRate; - } - - [StructLayout(LayoutKind.Sequential)] - private struct WLAN_SECURITY_ATTRIBUTES - { - [MarshalAs(UnmanagedType.Bool)] - public bool bSecurityEnabled; - - [MarshalAs(UnmanagedType.Bool)] - public bool bOneXEnabled; - - public DOT11_AUTH_ALGORITHM dot11AuthAlgorithm; - public DOT11_CIPHER_ALGORITHM dot11CipherAlgorithm; - } - - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] - private struct WLAN_PROFILE_INFO - { - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] - public string strProfileName; - - public uint dwFlags; - } - - [StructLayout(LayoutKind.Sequential)] - private struct WLAN_PROFILE_INFO_LIST - { - public uint dwNumberOfItems; - public uint dwIndex; - public WLAN_PROFILE_INFO[] ProfileInfo; - - public WLAN_PROFILE_INFO_LIST(IntPtr ppProfileList) - { - dwNumberOfItems = (uint)Marshal.ReadInt32(ppProfileList, 0); - dwIndex = (uint)Marshal.ReadInt32(ppProfileList, 4); - ProfileInfo = new WLAN_PROFILE_INFO[dwNumberOfItems]; - - var offset = Marshal.SizeOf(typeof(uint)) * 2; // Size of dwNumberOfItems and dwIndex - - for (int i = 0; i < dwNumberOfItems; i++) - { - var profileInfo = new IntPtr(ppProfileList.ToInt64() + (Marshal.SizeOf(typeof(WLAN_PROFILE_INFO)) * i) + offset); - ProfileInfo[i] = Marshal.PtrToStructure(profileInfo); - } - } - } - - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] - private struct WLAN_CONNECTION_PARAMETERS - { - public WLAN_CONNECTION_MODE wlanConnectionMode; - [MarshalAs(UnmanagedType.LPWStr)] - public string strProfile; - public IntPtr pDot11Ssid; // DOT11_SSID[] - public IntPtr pDesiredBssidList; // DOT11_BSSID_LIST[] - public DOT11_BSS_TYPE dot11BssType; - public uint dwFlags; - } - - [StructLayout(LayoutKind.Sequential)] - public struct DOT11_BSSID_LIST - { - public NDIS_OBJECT_HEADER Header; - public uint uNumOfEntries; - public uint uTotalNumOfEntries; - - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] - public byte[] BSSIDs; // DOT11_MAC_ADDRESS - } - - [StructLayout(LayoutKind.Sequential)] - public struct NDIS_OBJECT_HEADER - { - public byte Type; - public byte Revision; - public ushort Size; - } - - [StructLayout(LayoutKind.Sequential)] - private struct WLAN_NOTIFICATION_DATA - { - public uint NotificationSource; - public uint NotificationCode; - public Guid InterfaceGuid; - public uint dwDataSize; - public IntPtr pData; - } - - private enum WLAN_INTERFACE_STATE - { - wlan_interface_state_not_ready = 0, - wlan_interface_state_connected = 1, - wlan_interface_state_ad_hoc_network_formed = 2, - wlan_interface_state_disconnecting = 3, - wlan_interface_state_disconnected = 4, - wlan_interface_state_associating = 5, - wlan_interface_state_discovering = 6, - wlan_interface_state_authenticating = 7 - } - - private enum WLAN_CONNECTION_MODE - { - wlan_connection_mode_profile, - wlan_connection_mode_temporary_profile, - wlan_connection_mode_discovery_secure, - wlan_connection_mode_discovery_unsecure, - wlan_connection_mode_auto, - wlan_connection_mode_invalid - } - - private enum DOT11_BSS_TYPE - { - /// - /// Infrastructure BSS network - /// - dot11_BSS_type_infrastructure = 1, - - /// - /// Independent BSS (IBSS) network - /// - dot11_BSS_type_independent = 2, - - /// - /// Either infrastructure or IBSS network - /// - dot11_BSS_type_any = 3, - } - - private enum DOT11_PHY_TYPE : uint - { - dot11_phy_type_unknown = 0, - dot11_phy_type_any = 0, - dot11_phy_type_fhss = 1, - dot11_phy_type_dsss = 2, - dot11_phy_type_irbaseband = 3, - dot11_phy_type_ofdm = 4, - dot11_phy_type_hrdsss = 5, - dot11_phy_type_erp = 6, - dot11_phy_type_ht = 7, - dot11_phy_type_vht = 8, - dot11_phy_type_IHV_start = 0x80000000, - dot11_phy_type_IHV_end = 0xffffffff - } - - private enum DOT11_AUTH_ALGORITHM : uint - { - DOT11_AUTH_ALGO_80211_OPEN = 1, - DOT11_AUTH_ALGO_80211_SHARED_KEY = 2, - DOT11_AUTH_ALGO_WPA = 3, - DOT11_AUTH_ALGO_WPA_PSK = 4, - DOT11_AUTH_ALGO_WPA_NONE = 5, - DOT11_AUTH_ALGO_RSNA = 6, - DOT11_AUTH_ALGO_RSNA_PSK = 7, - DOT11_AUTH_ALGO_IHV_START = 0x80000000, - DOT11_AUTH_ALGO_IHV_END = 0xffffffff - } - - private enum DOT11_CIPHER_ALGORITHM : uint - { - DOT11_CIPHER_ALGO_NONE = 0x00, - DOT11_CIPHER_ALGO_WEP40 = 0x01, - DOT11_CIPHER_ALGO_TKIP = 0x02, - DOT11_CIPHER_ALGO_CCMP = 0x04, - DOT11_CIPHER_ALGO_WEP104 = 0x05, - DOT11_CIPHER_ALGO_WPA_USE_GROUP = 0x100, - DOT11_CIPHER_ALGO_RSN_USE_GROUP = 0x100, - DOT11_CIPHER_ALGO_WEP = 0x101, - DOT11_CIPHER_ALGO_IHV_START = 0x80000000, - DOT11_CIPHER_ALGO_IHV_END = 0xffffffff - } - - private enum WLAN_INTF_OPCODE : uint - { - wlan_intf_opcode_autoconf_start = 0x000000000, - wlan_intf_opcode_autoconf_enabled, - wlan_intf_opcode_background_scan_enabled, - wlan_intf_opcode_media_streaming_mode, - wlan_intf_opcode_radio_state, - wlan_intf_opcode_bss_type, - wlan_intf_opcode_interface_state, - wlan_intf_opcode_current_connection, - wlan_intf_opcode_channel_number, - wlan_intf_opcode_supported_infrastructure_auth_cipher_pairs, - wlan_intf_opcode_supported_adhoc_auth_cipher_pairs, - wlan_intf_opcode_supported_country_or_region_string_list, - wlan_intf_opcode_current_operation_mode, - wlan_intf_opcode_supported_safe_mode, - wlan_intf_opcode_certified_safe_mode, - wlan_intf_opcode_hosted_network_capable, - wlan_intf_opcode_management_frame_protection_capable, - wlan_intf_opcode_autoconf_end = 0x0fffffff, - wlan_intf_opcode_msm_start = 0x10000100, - wlan_intf_opcode_statistics, - wlan_intf_opcode_rssi, - wlan_intf_opcode_msm_end = 0x1fffffff, - wlan_intf_opcode_security_start = 0x20010000, - wlan_intf_opcode_security_end = 0x2fffffff, - wlan_intf_opcode_ihv_start = 0x30000000, - wlan_intf_opcode_ihv_end = 0x3fffffff - } - - private enum WLAN_NOTIFICATION_ACM : uint - { - wlan_notification_acm_start = 0, - wlan_notification_acm_autoconf_enabled, - wlan_notification_acm_autoconf_disabled, - wlan_notification_acm_background_scan_enabled, - wlan_notification_acm_background_scan_disabled, - wlan_notification_acm_bss_type_change, - wlan_notification_acm_power_setting_change, - wlan_notification_acm_scan_complete, - wlan_notification_acm_scan_fail, - wlan_notification_acm_connection_start, - wlan_notification_acm_connection_complete, - wlan_notification_acm_connection_attempt_fail, - wlan_notification_acm_filter_list_change, - wlan_notification_acm_interface_arrival, - wlan_notification_acm_interface_removal, - wlan_notification_acm_profile_change, - wlan_notification_acm_profile_name_change, - wlan_notification_acm_profiles_exhausted, - wlan_notification_acm_network_not_available, - wlan_notification_acm_network_available, - wlan_notification_acm_disconnecting, - wlan_notification_acm_disconnected, - wlan_notification_acm_adhoc_network_state_change, - wlan_notification_acm_profile_unblocked, - wlan_notification_acm_screen_power_change, - wlan_notification_acm_profile_blocked, - wlan_notification_acm_scan_list_refresh, - wlan_notification_acm_end - } - - private const uint WLAN_AVAILABLE_NETWORK_INCLUDE_ALL_ADHOC_PROFILES = 0x00000001; - private const uint WLAN_AVAILABLE_NETWORK_INCLUDE_ALL_MANUAL_HIDDEN_PROFILES = 0x00000002; - - private const uint ERROR_SUCCESS = 0; - private const uint ERROR_INVALID_PARAMETER = 87; - private const uint ERROR_INVALID_HANDLE = 6; - private const uint ERROR_INVALID_STATE = 5023; - private const uint ERROR_NOT_FOUND = 1168; - private const uint ERROR_NOT_ENOUGH_MEMORY = 8; - private const uint ERROR_ACCESS_DENIED = 5; - private const uint ERROR_NOT_SUPPORTED = 50; - private const uint ERROR_SERVICE_NOT_ACTIVE = 1062; - private const uint ERROR_NDIS_DOT11_AUTO_CONFIG_ENABLED = 0x80342000; - private const uint ERROR_NDIS_DOT11_MEDIA_IN_USE = 0x80342001; - private const uint ERROR_NDIS_DOT11_POWER_STATE_INVALID = 0x80342002; - - private const uint WLAN_NOTIFICATION_SOURCE_NONE = 0; - private const uint WLAN_NOTIFICATION_SOURCE_ALL = 0x0000FFFF; - private const uint WLAN_NOTIFICATION_SOURCE_ACM = 0x00000008; - private const uint WLAN_NOTIFICATION_SOURCE_HNWK = 0x00000080; - private const uint WLAN_NOTIFICATION_SOURCE_ONEX = 0x00000004; - private const uint WLAN_NOTIFICATION_SOURCE_MSM = 0x00000010; - private const uint WLAN_NOTIFICATION_SOURCE_SECURITY = 0x00000020; - private const uint WLAN_NOTIFICATION_SOURCE_IHV = 0x00000040; - - private const uint FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000; - - #endregion - - #region Type - - /// - /// BSS type - /// - public enum BssType - { - /// - /// None - /// - None = 0, - - /// - /// Infrastructure BSS network - /// - Infrastructure, - - /// - /// Independent BSS (IBSS) network (Ad hoc network) - /// - Independent, - - /// - /// Any BSS network - /// - Any - } - - /// - /// Wireless profile information - /// - public class ProfilePack - { - /// - /// Profile name - /// - public string Name { get; private set; } - - /// - /// GUID of associated wireless LAN interface - /// - public Guid InterfaceGuid { get; private set; } - - /// - /// Description of associated wireless LAN interface - /// - public string InterfaceDescription { get; private set; } - - /// - /// SSID of associated wireless LAN - /// - public string Ssid { get; private set; } - - /// - /// BSS type of associated wireless LAN - /// - public BssType BssType { get; private set; } - - /// - /// Authentication type of associated wireless LAN - /// - public string Authentication { get; private set; } - - /// - /// Encryption type of associated wireless LAN - /// - public string Encryption { get; private set; } - - /// - /// Position in preference order of associated wireless LAN interface - /// - public int Position { get; private set; } - - /// - /// Whether this profile is set to be automatically connected - /// - public bool IsAutomatic { get; private set; } - - /// - /// Signal level of associated wireless LAN - /// - public int Signal { get; private set; } - - /// - /// Whether this profile is currently connected - /// - public bool IsConnected { get; private set; } - - public ProfilePack( - string name, - Guid interfaceGuid, - string interfaceDescription, - string ssid, - BssType bssType, - string authentication, - string encryption, - int position, - bool isAutomatic, - int signal, - bool isConnected) - { - this.Name = name; - this.InterfaceGuid = interfaceGuid; - this.InterfaceDescription = interfaceDescription; - this.Ssid = ssid; - this.BssType = bssType; - this.Authentication = authentication; - this.Encryption = encryption; - this.Position = position; - this.IsAutomatic = isAutomatic; - this.Signal = signal; - this.IsConnected = isConnected; - } - } - - /// - /// Wireless LAN information - /// - public class NetworkPack - { - /// - /// GUID of associated wireless LAN interface - /// - public Guid InterfaceGuid { get; private set; } - - /// - /// SSID - /// - public string Ssid { get; private set; } - - /// - /// BSS type - /// - public BssType BssType { get; private set; } - - /// - /// Signal level - /// - public int Signal { get; private set; } - - /// - /// Name of associated wireless profile - /// - public string ProfileName { get; private set; } - - public NetworkPack(Guid interfaceGuid, string ssid, BssType bssType, int signal, string profileName) - { - this.InterfaceGuid = interfaceGuid; - this.Ssid = ssid; - this.BssType = bssType; - this.Signal = signal; - this.ProfileName = profileName; - } - } - - #endregion - - #region Scan networks - - /// - /// Request wireless interfaces to scan available wireless LANs. - /// - /// Timeout duration - /// Interface GUIDs that the requests succeeded - public static async Task> ScanAsync(TimeSpan timeoutDuration) - { - using (var client = new WlanClient()) - { - var interfaceInfoList = GetInterfaceInfoList(client.Handle); - var interfaceGuids = interfaceInfoList.Select(x => x.InterfaceGuid).ToArray(); - - var tcs = new TaskCompletionSource(); - var handler = new ScanHandler(tcs, interfaceGuids); - - Action callback = (data, context) => - { - var notificationData = Marshal.PtrToStructure(data); - if (notificationData.NotificationSource != WLAN_NOTIFICATION_SOURCE_ACM) - return; - - //Debug.WriteLine("Callback: {0}", (WLAN_NOTIFICATION_ACM)notificationData.NotificationCode); - - switch (notificationData.NotificationCode) - { - case (uint)WLAN_NOTIFICATION_ACM.wlan_notification_acm_scan_complete: - Debug.WriteLine("Scan succeeded."); - handler.SetSuccess(notificationData.InterfaceGuid); - break; - case (uint)WLAN_NOTIFICATION_ACM.wlan_notification_acm_scan_fail: - Debug.WriteLine("Scan failed."); - handler.SetFailure(notificationData.InterfaceGuid); - break; - } - }; - - RegisterNotification(client.Handle, WLAN_NOTIFICATION_SOURCE_ACM, callback); - - foreach (var interfaceGuid in interfaceGuids) - { - var result = Scan(client.Handle, interfaceGuid); - if (!result) - handler.SetFailure(interfaceGuid); - } - - var scanTask = tcs.Task; - await Task.WhenAny(scanTask, Task.Delay(timeoutDuration)); - - return handler.Results; - } - } - - private class ScanHandler - { - private TaskCompletionSource _tcs; - private readonly List _targets = new List(); - private readonly List _results = new List(); - - public IEnumerable Results { get { return _results.ToArray(); } } - - public ScanHandler(TaskCompletionSource tcs, IEnumerable targets) - { - this._tcs = tcs; - this._targets.AddRange(targets); - } - - private readonly object _locker = new object(); - - public void SetSuccess(Guid value) - { - lock (_locker) - { - _targets.Remove(value); - _results.Add(value); - - CheckTargets(); - } - } - - public void SetFailure(Guid value) - { - lock (_locker) - { - _targets.Remove(value); - - CheckTargets(); - } - } - - private void CheckTargets() - { - if ((_targets.Count <= 0) && !_tcs.Task.IsCompleted) - Task.Run(() => _tcs.SetResult(true)); - } - } - - #endregion - - #region Enumerate networks - - /// - /// Enumerate available wireless LANs. - /// - /// Wireless LANs - /// If multiple profiles are associated with a same network, there will be multiple entries - /// with the same SSID. - public static IEnumerable EnumerateAvailableNetworks() - { - using (var client = new WlanClient()) - { - var interfaceInfoList = GetInterfaceInfoList(client.Handle); - - foreach (var interfaceInfo in interfaceInfoList) - { - var availableNetworkList = GetAvailableNetworkList(client.Handle, interfaceInfo.InterfaceGuid); - - foreach (var availableNetwork in availableNetworkList) - { - //Debug.WriteLine("Interface: {0}, SSID: {1}, Signal: {2}", - // interfaceInfo.strInterfaceDescription, - // availableNetwork.dot11Ssid.ToSsidString(), - // availableNetwork.wlanSignalQuality); - - yield return new NetworkPack( - interfaceInfo.InterfaceGuid, - availableNetwork.dot11Ssid.ToSsidString(), - ConvertToBssType(availableNetwork.dot11BssType), - (int)availableNetwork.wlanSignalQuality, - availableNetwork.strProfileName); - } - } - } - } - - #endregion - - #region Enumerate Profiles - - /// - /// Enumerate wireless profiles in preference order. - /// - /// Wireless profiles - public static IEnumerable EnumerateProfiles() - { - using (var client = new WlanClient()) - { - var interfaceInfoList = GetInterfaceInfoList(client.Handle); - - foreach (var interfaceInfo in interfaceInfoList) - { - var availableNetworkList = GetAvailableNetworkList(client.Handle, interfaceInfo.InterfaceGuid) - .Where(x => !string.IsNullOrWhiteSpace(x.strProfileName)) - .ToArray(); - - var connection = GetConnectionAttributes(client.Handle, interfaceInfo.InterfaceGuid); - var interfaceIsConnected = (connection.isState == WLAN_INTERFACE_STATE.wlan_interface_state_connected); - - var profileInfoList = GetProfileInfoList(client.Handle, interfaceInfo.InterfaceGuid); - - int position = 0; - - foreach (var profileInfo in profileInfoList) - { - var availableNetwork = availableNetworkList.FirstOrDefault(x => x.strProfileName.Equals(profileInfo.strProfileName, StringComparison.Ordinal)); - var signal = (int)availableNetwork.wlanSignalQuality; - - var profileIsConnected = interfaceIsConnected && profileInfo.strProfileName.Equals(connection.strProfileName, StringComparison.Ordinal); - - //Debug.WriteLine("Interface: {0}, Profile: {1}, Position: {2}, Signal {3}, IsConnected {4}", - // interfaceInfo.strInterfaceDescription, - // profileInfo.strProfileName, - // position, - // signal, - // profileIsConnected); - - var profile = GetProfile( - client.Handle, - profileInfo.strProfileName, - interfaceInfo.InterfaceGuid, - interfaceInfo.strInterfaceDescription, - position++, - signal, - profileIsConnected); - - if (profile != null) - yield return profile; - } - } - } - } - - /// - /// Get a wireless profile. - /// - /// Client handle - /// Profile name - /// Interface GUID - /// Interface description - /// Whether this profile is connected to a wireless LAN - /// Wireless profile - /// - /// For profile elements, see - /// https://msdn.microsoft.com/en-us/library/windows/desktop/ms707381.aspx - /// - private static ProfilePack GetProfile(IntPtr clientHandle, string profileName, Guid interfaceGuid, string interfaceDescription, int position, int signal, bool isConnected) - { - var source = GetProfileXml(clientHandle, interfaceGuid, profileName); - if (string.IsNullOrWhiteSpace(source)) - return null; - - XElement rootXml; - using (var sr = new StringReader(source)) - rootXml = XElement.Load(sr); - - var ns = rootXml.Name.Namespace; - - var ssidXml = rootXml.Descendants(ns + "SSID").FirstOrDefault(); - var ssid = (ssidXml != null) ? ssidXml.Descendants(ns + "name").First().Value : null; - - var connectionTypeXml = rootXml.Descendants(ns + "connectionType").FirstOrDefault(); - var bssType = (connectionTypeXml != null) ? ConvertToBssType(connectionTypeXml.Value) : default(BssType); - - var connectionModeXml = rootXml.Descendants(ns + "connectionMode").FirstOrDefault(); - var isAutomatic = (connectionModeXml != null) && connectionModeXml.Value.Equals("auto", StringComparison.OrdinalIgnoreCase); - - var authenticationXml = rootXml.Descendants(ns + "authentication").FirstOrDefault(); - var authentication = (authenticationXml != null) ? authenticationXml.Value : null; - - var encryptionXml = rootXml.Descendants(ns + "encryption").FirstOrDefault(); - var encryption = (encryptionXml != null) ? encryptionXml.Value : null; - - //Debug.WriteLine("SSID: {0}, BssType: {1}, Authentication: {2}, Encryption: {3}, IsAutomatic: {4}", - // ssid, - // bssType, - // authentication, - // encryption, - // isAutomatic); - - return new ProfilePack( - profileName, - interfaceGuid, - interfaceDescription, - ssid, - bssType, - authentication, - encryption, - position, - isAutomatic, - signal, - isConnected); - } - - #endregion - - #region Set profile position - - /// - /// Set the position of a wireless profile in preference order. - /// - /// Profile name - /// Interface GUID - /// Position (starting from 0) - /// True if set. - public static bool SetProfilePosition(string profileName, Guid interfaceGuid, int position) - { - if (string.IsNullOrWhiteSpace(profileName)) - return false; - - if (interfaceGuid == default(Guid)) - return false; - - if (position < 0) - return false; - - using (var client = new WlanClient()) - { - return SetProfilePosition(client.Handle, interfaceGuid, profileName, (uint)position); - } - } - - #endregion - - #region Delete profile - - /// - /// Delete a wireless profile. - /// - /// Profile name - /// Interface GUID - /// True if deleted. False if could not delete. - public static bool DeleteProfile(string profileName, Guid interfaceGuid) - { - if (string.IsNullOrWhiteSpace(profileName)) - return false; - - if (interfaceGuid == default(Guid)) - return false; - - using (var client = new WlanClient()) - { - return DeleteProfile(client.Handle, interfaceGuid, profileName); - } - } - - #endregion - - #region Connect/Disconnect - - /// - /// Attempt to connect to a wireless LAN. - /// - /// Profile name - /// Interface GUID - /// BSS type - /// Timeout duration - /// True if succeeded. False if failed or timed out. - public static async Task ConnectAsync(string profileName, Guid interfaceGuid, BssType bssType, TimeSpan timeoutDuration) - { - if (string.IsNullOrWhiteSpace(profileName)) - return false; - - if (interfaceGuid == default(Guid)) - return false; - - using (var client = new WlanClient()) - { - var tcs = new TaskCompletionSource(); - - Action callback = (data, context) => - { - var notificationData = Marshal.PtrToStructure(data); - if (notificationData.NotificationSource != WLAN_NOTIFICATION_SOURCE_ACM) - return; - - //Debug.WriteLine("Callback: {0}", (WLAN_NOTIFICATION_ACM)notificationData.NotificationCode); - - switch (notificationData.NotificationCode) - { - case (uint)WLAN_NOTIFICATION_ACM.wlan_notification_acm_connection_complete: - Task.Run(() => tcs.SetResult(true)); - break; - case (uint)WLAN_NOTIFICATION_ACM.wlan_notification_acm_connection_attempt_fail: - Task.Run(() => tcs.SetResult(false)); - break; - } - }; - - RegisterNotification(client.Handle, WLAN_NOTIFICATION_SOURCE_ACM, callback); - - var result = Connect(client.Handle, interfaceGuid, profileName, ConvertFromBssType(bssType)); - if (!result) - tcs.SetResult(false); - - var connectTask = tcs.Task; - var completedTask = await Task.WhenAny(connectTask, Task.Delay(timeoutDuration)); - - return (completedTask == connectTask) ? connectTask.Result : false; - } - } - - /// - /// Disconnect from a wireless LAN. - /// - /// Interface GUID - /// Timeout duration - /// True if succeeded. False if failed or timed out. - public static async Task DisconnectAsync(Guid interfaceGuid, TimeSpan timeoutDuration) - { - if (interfaceGuid == default(Guid)) - return false; - - using (var client = new WlanClient()) - { - var tcs = new TaskCompletionSource(); - - Action callback = (data, context) => - { - var notificationData = Marshal.PtrToStructure(data); - if (notificationData.NotificationSource != WLAN_NOTIFICATION_SOURCE_ACM) - return; - - //Debug.WriteLine("Callback: {0}", (WLAN_NOTIFICATION_ACM)notificationData.NotificationCode); - - switch (notificationData.NotificationCode) - { - case (uint)WLAN_NOTIFICATION_ACM.wlan_notification_acm_disconnected: - Task.Run(() => tcs.SetResult(true)); - break; - } - }; - - RegisterNotification(client.Handle, WLAN_NOTIFICATION_SOURCE_ACM, callback); - - var result = Disconnect(client.Handle, interfaceGuid); - if (!result) - tcs.SetResult(false); - - var disconnectTask = tcs.Task; - var completedTask = await Task.WhenAny(disconnectTask, Task.Delay(timeoutDuration)); - - return (completedTask == disconnectTask) ? disconnectTask.Result : false; - } - } - - #endregion - - #region Helper - - private static DOT11_BSS_TYPE ConvertFromBssType(BssType source) - { - switch (source) - { - case BssType.Infrastructure: - return DOT11_BSS_TYPE.dot11_BSS_type_infrastructure; - case BssType.Independent: - return DOT11_BSS_TYPE.dot11_BSS_type_independent; - default: - return DOT11_BSS_TYPE.dot11_BSS_type_any; - } - } - - private static BssType ConvertToBssType(DOT11_BSS_TYPE source) - { - switch (source) - { - case DOT11_BSS_TYPE.dot11_BSS_type_infrastructure: - return BssType.Infrastructure; - case DOT11_BSS_TYPE.dot11_BSS_type_independent: - return BssType.Independent; - default: - return BssType.Any; - } - } - - private static BssType ConvertToBssType(string source) - { - if (string.IsNullOrWhiteSpace(source)) - { - return default(BssType); - } - if (source.Equals("ESS", StringComparison.OrdinalIgnoreCase)) - { - return BssType.Infrastructure; - } - if (source.Equals("IBSS", StringComparison.OrdinalIgnoreCase)) - { - return BssType.Independent; - } - return BssType.Any; - } - - #endregion - - #region Base - - private class WlanClient : IDisposable - { - private IntPtr _clientHandle = IntPtr.Zero; - - public IntPtr Handle { get { return _clientHandle; } } - - public WlanClient() - { - uint negotiatedVersion; - var result = WlanOpenHandle( - 2, // Client version for Windows Vista and Windows Server 2008 - IntPtr.Zero, - out negotiatedVersion, - out _clientHandle); - - CheckResult(result, "WlanOpenHandle", true); - } - - #region Dispose - - private bool _disposed = false; - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - protected virtual void Dispose(bool disposing) - { - if (_disposed) - return; - - if (_clientHandle != IntPtr.Zero) - WlanCloseHandle(_clientHandle, IntPtr.Zero); - - _disposed = true; - } - - ~WlanClient() - { - Dispose(false); - } - - #endregion - } - - private static WLAN_INTERFACE_INFO[] GetInterfaceInfoList(IntPtr clientHandle) - { - var interfaceList = IntPtr.Zero; - try - { - var result = WlanEnumInterfaces( - clientHandle, - IntPtr.Zero, - out interfaceList); - - return CheckResult(result, "WlanEnumInterfaces", true) - ? new WLAN_INTERFACE_INFO_LIST(interfaceList).InterfaceInfo - : null; // Not to be used - } - finally - { - if (interfaceList != IntPtr.Zero) - WlanFreeMemory(interfaceList); - } - } - - private static bool Scan(IntPtr clientHandle, Guid interfaceGuid) - { - var result = WlanScan( - clientHandle, - interfaceGuid, - IntPtr.Zero, - IntPtr.Zero, - IntPtr.Zero); - - // ERROR_NDIS_DOT11_POWER_STATE_INVALID will be returned if the interface is turned off. - return CheckResult(result, "WlanScan", false); - } - - private static WLAN_AVAILABLE_NETWORK[] GetAvailableNetworkList(IntPtr clientHandle, Guid interfaceGuid) - { - var availableNetworkList = IntPtr.Zero; - try - { - var result = WlanGetAvailableNetworkList( - clientHandle, - interfaceGuid, - WLAN_AVAILABLE_NETWORK_INCLUDE_ALL_MANUAL_HIDDEN_PROFILES, - IntPtr.Zero, - out availableNetworkList); - - // ERROR_NDIS_DOT11_POWER_STATE_INVALID will be returned if the interface is turned off. - return CheckResult(result, "WlanGetAvailableNetworkList", false) - ? new WLAN_AVAILABLE_NETWORK_LIST(availableNetworkList).Network - : new WLAN_AVAILABLE_NETWORK[] { }; - } - finally - { - if (availableNetworkList != IntPtr.Zero) - WlanFreeMemory(availableNetworkList); - } - } - - private static WLAN_CONNECTION_ATTRIBUTES GetConnectionAttributes(IntPtr clientHandle, Guid interfaceGuid) - { - var queryData = IntPtr.Zero; - try - { - uint dataSize; - var result = WlanQueryInterface( - clientHandle, - interfaceGuid, - WLAN_INTF_OPCODE.wlan_intf_opcode_current_connection, - IntPtr.Zero, - out dataSize, - ref queryData, - IntPtr.Zero); - - // ERROR_INVALID_STATE will be returned if the client is not connected to a network. - return CheckResult(result, "WlanQueryInterface", false) - ? Marshal.PtrToStructure(queryData) - : default(WLAN_CONNECTION_ATTRIBUTES); - } - finally - { - if (queryData != IntPtr.Zero) - WlanFreeMemory(queryData); - } - } - - private static WLAN_PROFILE_INFO[] GetProfileInfoList(IntPtr clientHandle, Guid interfaceGuid) - { - var profileList = IntPtr.Zero; - try - { - var result = WlanGetProfileList( - clientHandle, - interfaceGuid, - IntPtr.Zero, - out profileList); - - return CheckResult(result, "WlanGetProfileList", false) - ? new WLAN_PROFILE_INFO_LIST(profileList).ProfileInfo - : new WLAN_PROFILE_INFO[] { }; - } - finally - { - if (profileList != IntPtr.Zero) - WlanFreeMemory(profileList); - } - } - - private static string GetProfileXml(IntPtr clientHandle, Guid interfaceGuid, string profileName) - { - var profileXml = IntPtr.Zero; - try - { - uint flags = 0U; - uint grantedAccess; - var result = WlanGetProfile( - clientHandle, - interfaceGuid, - profileName, - IntPtr.Zero, - out profileXml, - ref flags, - out grantedAccess); - - // ERROR_NOT_FOUND will be returned if the profile is not found. - return CheckResult(result, "WlanGetProfile", false) - ? Marshal.PtrToStringUni(profileXml) - : null; // To be used - } - finally - { - if (profileXml != IntPtr.Zero) - WlanFreeMemory(profileXml); - } - } - - private static bool SetProfilePosition(IntPtr clientHandle, Guid interfaceGuid, string profileName, uint position) - { - var result = WlanSetProfilePosition( - clientHandle, - interfaceGuid, - profileName, - position, - IntPtr.Zero); - - // ERROR_INVALID_PARAMETER will be returned if the interface is removed. - // ERROR_NOT_FOUND will be returned if the position of a profile is invalid. - return CheckResult(result, "WlanSetProfilePosition", false); - } - - private static bool DeleteProfile(IntPtr clientHandle, Guid interfaceGuid, string profileName) - { - var result = WlanDeleteProfile( - clientHandle, - interfaceGuid, - profileName, - IntPtr.Zero); - - // ERROR_INVALID_PARAMETER will be returned if the interface is removed. - // ERROR_NOT_FOUND will be returned if the profile is not found. - return CheckResult(result, "WlanDeleteProfile", false); - } - - private static bool Connect(IntPtr clientHandle, Guid interfaceGuid, string profileName, DOT11_BSS_TYPE bssType) - { - var connectionParameters = new WLAN_CONNECTION_PARAMETERS - { - wlanConnectionMode = WLAN_CONNECTION_MODE.wlan_connection_mode_profile, - strProfile = profileName, - dot11BssType = bssType, - dwFlags = 0U - }; - - var result = WlanConnect( - clientHandle, - interfaceGuid, - ref connectionParameters, - IntPtr.Zero); - - // ERROR_NOT_FOUND will be returned if the interface is removed. - return CheckResult(result, "WlanConnect", false); - } - - private static bool Disconnect(IntPtr clientHandle, Guid interfaceGuid) - { - var result = WlanDisconnect( - clientHandle, - interfaceGuid, - IntPtr.Zero); - - // ERROR_NOT_FOUND will be returned if the interface is removed. - return CheckResult(result, "WlanDisconnect", false); - } - - private static void RegisterNotification(IntPtr clientHandle, uint notificationSource, Action callback) - { - // Storing a delegate in class field is necessary to prevent garbage collector from collecting it - // before the delegate is called. Otherwise, CallbackOnCollectedDelegate may occur. - _notificationCallback = new WLAN_NOTIFICATION_CALLBACK(callback); - - var result = WlanRegisterNotification(clientHandle, - notificationSource, - false, - _notificationCallback, - IntPtr.Zero, - IntPtr.Zero, - 0); - - CheckResult(result, "WlanRegisterNotification", true); - } - - private static WLAN_NOTIFICATION_CALLBACK _notificationCallback; - - private static bool CheckResult(uint result, string methodName, bool willThrowOnFailure) - { - if (result == ERROR_SUCCESS) - return true; - - if (!willThrowOnFailure) - { - switch (result) - { - case ERROR_INVALID_PARAMETER: - case ERROR_INVALID_STATE: - case ERROR_NOT_FOUND: - case ERROR_NOT_ENOUGH_MEMORY: - case ERROR_ACCESS_DENIED: - case ERROR_NOT_SUPPORTED: - case ERROR_SERVICE_NOT_ACTIVE: - case ERROR_NDIS_DOT11_AUTO_CONFIG_ENABLED: - case ERROR_NDIS_DOT11_MEDIA_IN_USE: - case ERROR_NDIS_DOT11_POWER_STATE_INVALID: - return false; - - case ERROR_INVALID_HANDLE: - break; - } - } - throw CreateWin32Exception(result, methodName); - } - - private static Win32Exception CreateWin32Exception(uint errorCode, string methodName) - { - var sb = new StringBuilder(512); // This 512 capacity is arbitrary. - - var result = FormatMessage( - FORMAT_MESSAGE_FROM_SYSTEM, - IntPtr.Zero, - errorCode, - 0x0409, // US (English) - sb, - sb.Capacity, - IntPtr.Zero); - - var message = string.Format("Method: {0}, Code: {1}", methodName, errorCode); - if (0 < result) - message += string.Format(", Message: {0}", sb.ToString()); - - return new Win32Exception((int)errorCode, message); - } - - #endregion - } -} \ No newline at end of file diff --git a/WlanProfileViewer/Models/Wlan/NativeWifiWorker.cs b/WlanProfileViewer/Models/Wlan/NativeWifiWorker.cs index ebca11e..a530c51 100644 --- a/WlanProfileViewer/Models/Wlan/NativeWifiWorker.cs +++ b/WlanProfileViewer/Models/Wlan/NativeWifiWorker.cs @@ -5,29 +5,31 @@ using System.Threading; using System.Threading.Tasks; +using ManagedNativeWifi; + namespace WlanProfileViewer.Models.Wlan { internal class NativeWifiWorker : IWlanWorker { #region Get profiles - public async Task> GetProfilesAsync(bool isLatest, TimeSpan timeoutDuration) + public async Task> GetProfilesAsync(bool isLatest, TimeSpan timeout) { if (isLatest) - await NativeWifi.ScanAsync(timeoutDuration).ConfigureAwait(false); + await NativeWifi.ScanNetworksAsync(timeout).ConfigureAwait(false); var profilePacks = await Task.Run(() => NativeWifi.EnumerateProfiles()).ConfigureAwait(false); return profilePacks.Select(x => new ProfileItem( name: x.Name, - interfaceGuid: x.InterfaceGuid, + interfaceId: x.Interface.Id, interfaceName: null, - interfaceDescription: x.InterfaceDescription, + interfaceDescription: x.Interface.Description, authentication: ConvertToAuthentication(x.Authentication), encryption: ConvertToEncryption(x.Encryption), position: x.Position, isAutomatic: x.IsAutomatic, - signal: x.Signal, + signal: x.SignalQuality, isConnected: x.IsConnected)); } @@ -72,7 +74,7 @@ public async Task SetProfilePositionAsync(ProfileItem profileItem, int pos if (position < 0) throw new ArgumentOutOfRangeException(nameof(position)); - return await Task.Run(() => NativeWifi.SetProfilePosition(profileItem.Name, profileItem.InterfaceGuid, position)); + return await Task.Run(() => NativeWifi.SetProfilePosition(profileItem.InterfaceId, profileItem.Name, position)); } #endregion @@ -84,27 +86,27 @@ public async Task DeleteProfileAsync(ProfileItem profileItem) if (profileItem == null) throw new ArgumentNullException(nameof(profileItem)); - return await Task.Run(() => NativeWifi.DeleteProfile(profileItem.Name, profileItem.InterfaceGuid)); + return await Task.Run(() => NativeWifi.DeleteProfile(profileItem.InterfaceId, profileItem.Name)); } #endregion #region Connect/Disconnect - public async Task ConnectAsync(ProfileItem profileItem, TimeSpan timeoutDuration) + public async Task ConnectNetworkAsync(ProfileItem profileItem, TimeSpan timeout) { if (profileItem == null) throw new ArgumentNullException(nameof(profileItem)); - return await NativeWifi.ConnectAsync(profileItem.Name, profileItem.InterfaceGuid, NativeWifi.BssType.Any, timeoutDuration); + return await NativeWifi.ConnectNetworkAsync(profileItem.InterfaceId, profileItem.Name, BssType.Any, timeout); } - public async Task DisconnectAsync(ProfileItem profileItem, TimeSpan timeoutDuration) + public async Task DisconnectNetworkAsync(ProfileItem profileItem, TimeSpan timeout) { if (profileItem == null) throw new ArgumentNullException(nameof(profileItem)); - return await NativeWifi.DisconnectAsync(profileItem.InterfaceGuid, timeoutDuration); + return await NativeWifi.DisconnectNetworkAsync(profileItem.InterfaceId, timeout); } #endregion diff --git a/WlanProfileViewer/Models/Wlan/Netsh.cs b/WlanProfileViewer/Models/Wlan/Netsh.cs index 86f70fa..52be87b 100644 --- a/WlanProfileViewer/Models/Wlan/Netsh.cs +++ b/WlanProfileViewer/Models/Wlan/Netsh.cs @@ -29,9 +29,9 @@ public enum NetworkType private class ShortProfilePack { - public string Name { get; set; } - public string InterfaceName { get; set; } - public int Position { get; set; } + public string Name { get; } + public string InterfaceName { get; } + public int Position { get; } public ShortProfilePack(string name, string interfaceName, int position) { @@ -43,20 +43,20 @@ public ShortProfilePack(string name, string interfaceName, int position) public class ProfilePack { - public string Name { get; private set; } - public string InterfaceName { get; private set; } - public string Ssid { get; private set; } - public NetworkType NetworkType { get; private set; } - public string Authentication { get; private set; } - public string Encryption { get; private set; } - public int Position { get; private set; } - public bool IsAutomatic { get; private set; } + public string Name { get; } + public string InterfaceName { get; } + public string Ssid { get; } + public NetworkType NetworkType { get; } + public string Authentication { get; } + public string Encryption { get; } + public int Position { get; } + public bool IsAutomatic { get; } public ProfilePack( string name, string interfaceName, string ssid, - NetworkType netwotrkType, + NetworkType networkType, string authentication, string encryption, int position, @@ -65,7 +65,7 @@ public ProfilePack( this.Name = name; this.InterfaceName = interfaceName; this.Ssid = ssid; - this.NetworkType = netwotrkType; + this.NetworkType = networkType; this.Authentication = authentication; this.Encryption = encryption; this.Position = position; @@ -75,24 +75,24 @@ public ProfilePack( public class InterfacePack { - public string Name { get; private set; } - public string Description { get; private set; } - public Guid Guid { get; private set; } - public string PhysicalAddress { get; private set; } - public bool IsConnected { get; private set; } - public string ProfileName { get; private set; } + public string Name { get; } + public string Description { get; } + public Guid Id { get; } + public string PhysicalAddress { get; } + public bool IsConnected { get; } + public string ProfileName { get; } public InterfacePack( string name, string description, - Guid guid, + Guid id, string physicalAddress, bool isConnected, string profileName) { this.Name = name; this.Description = description; - this.Guid = guid; + this.Id = id; this.PhysicalAddress = physicalAddress; this.IsConnected = isConnected; this.ProfileName = profileName; @@ -101,12 +101,12 @@ public InterfacePack( public class NetworkPack { - public string InterfaceName { get; private set; } - public string Ssid { get; private set; } - public NetworkType NetworkType { get; private set; } - public string Authenticaion { get; private set; } - public string Encryption { get; private set; } - public int Signal { get; private set; } + public string InterfaceName { get; } + public string Ssid { get; } + public NetworkType NetworkType { get; } + public string Authenticaion { get; } + public string Encryption { get; } + public int Signal { get; } public NetworkPack( string interfaceName, @@ -142,7 +142,7 @@ private static IEnumerable EnumerateInterfaces(IEnumerable EnumerateInterfaces(IEnumerable EnumerateInterfaces(IEnumerable EnumerateNetworks(IEnumerable ou // encryption, // signal.Value); - yield return new NetworkPack(interfaceName, ssid, networkType, authentication, encryption, signal.Value); + yield return new NetworkPack( + interfaceName: interfaceName, + ssid: ssid, + networkType: networkType, + authentication: authentication, + encryption: encryption, + signal: signal.Value); ssid = null; networkType = default(NetworkType); @@ -315,7 +327,7 @@ public static async Task> GetProfilesAsync() var shortProfiles = EnumerateShortProfiles(outputLines); - return (await Task.WhenAll(shortProfiles.Select(async x => await GetProfileAsync(x.Name, x.InterfaceName, x.Position)))) + return (await Task.WhenAll(shortProfiles.Select(async x => await GetProfileAsync(x.InterfaceName, x.Name, x.Position)))) .Where(x => x != null); } @@ -347,22 +359,22 @@ private static IEnumerable EnumerateShortProfiles(IEnumerable< } } - public static async Task GetProfileAsync(string profileName, string interfaceName, int position) + public static async Task GetProfileAsync(string interfaceName, string profileName, int position) { - if (string.IsNullOrWhiteSpace(profileName)) - return null; - if (string.IsNullOrWhiteSpace(interfaceName)) - return null; + throw new ArgumentNullException(nameof(interfaceName)); + + if (string.IsNullOrWhiteSpace(profileName)) + throw new ArgumentNullException(nameof(profileName)); var command = $@"netsh wlan show profile name=""{profileName}"" interface=""{interfaceName}"""; var outputLines = await ExecuteNetshAsync(command).ConfigureAwait(false); - return GetProfile(outputLines, profileName, interfaceName, position); + return GetProfile(outputLines, interfaceName, profileName, position); } - private static ProfilePack GetProfile(IEnumerable outputLines, string profileName, string interfaceName, int position) + private static ProfilePack GetProfile(IEnumerable outputLines, string interfaceName, string profileName, int position) { bool? isAutomatic = null; string ssid = null; @@ -420,7 +432,7 @@ private static ProfilePack GetProfile(IEnumerable outputLines, string pr (encryption == null)) return null; - //Debug.WriteLine("Profile: {0}, Interface: {1}, SSID: {2}, BSS type: {3}, Authentication: {4}, Encryption: {5}, Position: {6}, IsAutomatic: {7}", + //Debug.WriteLine("Profile: {0}, Interface: {1}, SSID: {2}, BSS: {3}, Authentication: {4}, Encryption: {5}, Position: {6}, IsAutomatic: {7}", // profileName, // interfaceName, // ssid, @@ -431,30 +443,30 @@ private static ProfilePack GetProfile(IEnumerable outputLines, string pr // isAutomatic.Value); return new ProfilePack( - profileName, - interfaceName, - ssid, - networkType, - authentication, - encryption, - position, - isAutomatic.Value); + name: profileName, + interfaceName: interfaceName, + ssid: ssid, + networkType: networkType, + authentication: authentication, + encryption: encryption, + position: position, + isAutomatic: isAutomatic.Value); } #endregion #region Set profile position - public static async Task SetProfilePositionAync(string profileName, string interfaceName, int position) + public static async Task SetProfilePositionAync(string interfaceName, string profileName, int position) { - if (string.IsNullOrWhiteSpace(profileName)) - return false; - if (string.IsNullOrWhiteSpace(interfaceName)) - return false; + throw new ArgumentNullException(nameof(interfaceName)); + + if (string.IsNullOrWhiteSpace(profileName)) + throw new ArgumentNullException(nameof(profileName)); if (position < 0) - return false; + throw new ArgumentOutOfRangeException(nameof(position)); position++; // According to the error message, "Profile preference order starts with 1." @@ -471,10 +483,10 @@ public static async Task SetProfilePositionAync(string profileName, string #region Delete profile - public static async Task DeleteProfileAsync(string profileName, string interfaceName) + public static async Task DeleteProfileAsync(string interfaceName, string profileName) { if (string.IsNullOrWhiteSpace(profileName)) - return false; + throw new ArgumentNullException(nameof(profileName)); var command = $@"netsh wlan delete profile name=""{profileName}"""; if (!string.IsNullOrWhiteSpace(interfaceName)) @@ -493,13 +505,13 @@ public static async Task DeleteProfileAsync(string profileName, string int #region Connect/Disconnect - public static async Task ConnectAsync(string profileName, string interfaceName) + public static async Task ConnectNetworkAsync(string interfaceName, string profileName) { - if (string.IsNullOrWhiteSpace(profileName)) - return false; - if (string.IsNullOrWhiteSpace(interfaceName)) - return false; + throw new ArgumentNullException(nameof(interfaceName)); + + if (string.IsNullOrWhiteSpace(profileName)) + throw new ArgumentNullException(nameof(profileName)); var command = $@"netsh wlan connect name=""{profileName}"" interface=""{interfaceName}"""; @@ -510,10 +522,10 @@ public static async Task ConnectAsync(string profileName, string interface return outputLines.Contains(expected); } - public static async Task DisconnectAsync(string interfaceName) + public static async Task DisconnectNetworkAsync(string interfaceName) { if (string.IsNullOrWhiteSpace(interfaceName)) - return false; + throw new ArgumentNullException(nameof(interfaceName)); var command = $@"netsh wlan disconnect interface=""{interfaceName}"""; diff --git a/WlanProfileViewer/Models/Wlan/NetshWorker.cs b/WlanProfileViewer/Models/Wlan/NetshWorker.cs index 0942efe..f5fc174 100644 --- a/WlanProfileViewer/Models/Wlan/NetshWorker.cs +++ b/WlanProfileViewer/Models/Wlan/NetshWorker.cs @@ -10,7 +10,7 @@ internal class NetshWorker : IWlanWorker { #region Get profiles - public async Task> GetProfilesAsync(bool isLatest, TimeSpan timeoutDuration) + public async Task> GetProfilesAsync(bool isLatest, TimeSpan timeout) { var interfacePacks = (await Netsh.GetInterfacesAsync().ConfigureAwait(false)) .ToArray(); // ToArray method is necessary. @@ -28,7 +28,7 @@ from interfacePack in interfacePacks where profilePack.InterfaceName.Equals(interfacePack.Name, StringComparison.Ordinal) select new ProfileItem( name: profilePack.Name, - interfaceGuid: interfacePack.Guid, + interfaceId: interfacePack.Id, interfaceName: profilePack.InterfaceName, interfaceDescription: interfacePack.Description, authentication: ConvertToAuthentication(profilePack.Authentication), @@ -87,7 +87,7 @@ public async Task SetProfilePositionAsync(ProfileItem profileItem, int pos if (position < 0) throw new ArgumentOutOfRangeException(nameof(position)); - return await Netsh.SetProfilePositionAync(profileItem.Name, profileItem.InterfaceName, position); + return await Netsh.SetProfilePositionAync(profileItem.InterfaceName, profileItem.Name, position); } #endregion @@ -99,27 +99,27 @@ public async Task DeleteProfileAsync(ProfileItem profileItem) if (profileItem == null) throw new ArgumentNullException(nameof(profileItem)); - return await Netsh.DeleteProfileAsync(profileItem.Name, profileItem.InterfaceName); + return await Netsh.DeleteProfileAsync(profileItem.InterfaceName, profileItem.Name); } #endregion #region Connect/Disconnect - public async Task ConnectAsync(ProfileItem profileItem, TimeSpan timeoutDuration) + public async Task ConnectNetworkAsync(ProfileItem profileItem, TimeSpan timeout) { if (profileItem == null) throw new ArgumentNullException(nameof(profileItem)); - return await Netsh.ConnectAsync(profileItem.Name, profileItem.InterfaceName); + return await Netsh.ConnectNetworkAsync(profileItem.InterfaceName, profileItem.Name); } - public async Task DisconnectAsync(ProfileItem profileItem, TimeSpan timeoutDuration) + public async Task DisconnectNetworkAsync(ProfileItem profileItem, TimeSpan timeout) { if (profileItem == null) throw new ArgumentNullException(nameof(profileItem)); - return await Netsh.DisconnectAsync(profileItem.InterfaceName); + return await Netsh.DisconnectNetworkAsync(profileItem.InterfaceName); } #endregion diff --git a/WlanProfileViewer/Models/Wlan/ProfileItem.cs b/WlanProfileViewer/Models/Wlan/ProfileItem.cs index 83a9464..af9abb4 100644 --- a/WlanProfileViewer/Models/Wlan/ProfileItem.cs +++ b/WlanProfileViewer/Models/Wlan/ProfileItem.cs @@ -17,9 +17,9 @@ public class ProfileItem : BindableBase public string Name { get; } /// - /// Interface GUID + /// Interface ID /// - public Guid InterfaceGuid { get; } + public Guid InterfaceId { get; } /// /// Interface name (only for Netsh) @@ -44,7 +44,7 @@ public class ProfileItem : BindableBase /// /// Profile ID /// - public string Id => _id ?? (_id = Name + InterfaceGuid.ToString()); + public string Id => _id ?? (_id = Name + InterfaceId.ToString()); private string _id; /// @@ -114,7 +114,7 @@ public bool IsConnected public ProfileItem( string name, - Guid interfaceGuid, + Guid interfaceId, string interfaceName, string interfaceDescription, AuthenticationMethod authentication, @@ -127,11 +127,11 @@ public ProfileItem( if (string.IsNullOrWhiteSpace(name)) throw new ArgumentNullException(nameof(name)); - if (interfaceGuid == default(Guid)) - throw new ArgumentException(nameof(interfaceGuid)); + if (interfaceId == Guid.Empty) + throw new ArgumentException(nameof(interfaceId)); this.Name = name; - this.InterfaceGuid = interfaceGuid; + this.InterfaceId = interfaceId; this.InterfaceName = interfaceName; this.InterfaceDescription = interfaceDescription; this.Authentication = authentication; diff --git a/WlanProfileViewer/Properties/AssemblyInfo.cs b/WlanProfileViewer/Properties/AssemblyInfo.cs index 5890f14..dbaa559 100644 --- a/WlanProfileViewer/Properties/AssemblyInfo.cs +++ b/WlanProfileViewer/Properties/AssemblyInfo.cs @@ -51,5 +51,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.2")] -[assembly: AssemblyFileVersion("1.0.0.2")] +[assembly: AssemblyVersion("1.1.0.4")] +[assembly: AssemblyFileVersion("1.1.0.4")] diff --git a/WlanProfileViewer/ViewModels/MainWindowViewModel.cs b/WlanProfileViewer/ViewModels/MainWindowViewModel.cs index ca41a0e..3fe4762 100644 --- a/WlanProfileViewer/ViewModels/MainWindowViewModel.cs +++ b/WlanProfileViewer/ViewModels/MainWindowViewModel.cs @@ -182,7 +182,7 @@ public MainWindowViewModel() .CombineLatestValuesAreAllTrue() .ToReactiveCommand(); ConnectCommand - .Subscribe(async _ => await Op.ConnectAsync()); + .Subscribe(async _ => await Op.ConnectNetworkAsync()); #endregion @@ -195,7 +195,7 @@ public MainWindowViewModel() .CombineLatestValuesAreAllTrue() .ToReactiveCommand(); DisconnectCommand - .Subscribe(async _ => await Op.DisconnectAsync()); + .Subscribe(async _ => await Op.DisconnectNetworkAsync()); #endregion diff --git a/WlanProfileViewer/WlanProfileViewer.csproj b/WlanProfileViewer/WlanProfileViewer.csproj index e236e73..56e4757 100644 --- a/WlanProfileViewer/WlanProfileViewer.csproj +++ b/WlanProfileViewer/WlanProfileViewer.csproj @@ -41,21 +41,25 @@ Resources\ring.ico + + False + Library\ManagedNativeWifi.dll + False Library\MonitorAware.dll - ..\packages\ReactiveProperty.2.2.3.1\lib\net45\ReactiveProperty.dll + ..\packages\ReactiveProperty.2.2.8\lib\net45\ReactiveProperty.dll True - ..\packages\ReactiveProperty.2.2.3.1\lib\net45\ReactiveProperty.DataAnnotations.dll + ..\packages\ReactiveProperty.2.2.8\lib\net45\ReactiveProperty.DataAnnotations.dll True - ..\packages\ReactiveProperty.2.2.3.1\lib\net45\ReactiveProperty.NET45.dll + ..\packages\ReactiveProperty.2.2.8\lib\net45\ReactiveProperty.NET45.dll True @@ -118,7 +122,6 @@ - @@ -196,6 +199,8 @@ + + diff --git a/WlanProfileViewer/packages.config b/WlanProfileViewer/packages.config index 99ac362..88a6a63 100644 --- a/WlanProfileViewer/packages.config +++ b/WlanProfileViewer/packages.config @@ -1,6 +1,6 @@  - +