/// <summary> /// Gets wireless interface radio information of a specified wireless interface. /// </summary> /// <param name="interfaceId">Interface ID</param> /// <returns>Wireless interface radio information if succeeded. Null if not.</returns> public static InterfaceRadio GetInterfaceRadio(Guid interfaceId) { if (interfaceId == Guid.Empty) { throw new ArgumentException(nameof(interfaceId)); } using (var client = new Base.WlanClient()) { var capability = Base.GetInterfaceCapability(client.Handle, interfaceId); var states = Base.GetPhyRadioStates(client.Handle, interfaceId); // The underlying collection is array. if ((capability.interfaceType == WLAN_INTERFACE_TYPE.wlan_interface_type_invalid) || (capability.dwNumberOfSupportedPhys != states.Count())) { return(null); } var radioSets = Enumerable.Zip( capability.dot11PhyTypes, states.OrderBy(x => x.dwPhyIndex), (x, y) => new RadioSet( type: ConvertToPhyType(x), softwareOn: ConvertToNullableBoolean(y.dot11SoftwareRadioState), hardwareOn: ConvertToNullableBoolean(y.dot11HardwareRadioState))); return(new InterfaceRadio( id: interfaceId, radioSets: radioSets)); } }
/// <summary> /// Enumerates SSIDs of connected wireless LANs. /// </summary> /// <returns>SSIDs</returns> public static IEnumerable <NetworkIdentifier> EnumerateConnectedNetworkSsids() { using (var client = new Base.WlanClient()) { var interfaceInfoList = Base.GetInterfaceInfoList(client.Handle); foreach (var interfaceInfo in interfaceInfoList) { var connection = Base.GetConnectionAttributes(client.Handle, interfaceInfo.InterfaceGuid); if (connection.isState != WLAN_INTERFACE_STATE.wlan_interface_state_connected) { continue; } var association = connection.wlanAssociationAttributes; //Debug.WriteLine("Interface: {0}, SSID: {1}, BSSID: {2}, Signal: {3}", // interfaceInfo.strInterfaceDescription, // association.dot11Ssid, // association.dot11Bssid, // association.wlanSignalQuality); yield return(new NetworkIdentifier(association.dot11Ssid.ToBytes(), association.dot11Ssid.ToString())); } } }
/// <summary> /// Enumerates wireless LAN information on BSS networks. /// </summary> /// <returns>Wireless LAN information</returns> public static IEnumerable <BssNetworkPack> EnumerateBssNetworks() { using (var client = new Base.WlanClient()) { var interfaceInfoList = Base.GetInterfaceInfoList(client.Handle); foreach (var interfaceInfo in interfaceInfoList.Select(x => ConvertToInterfaceInfo(x))) { var networkBssEntryList = Base.GetNetworkBssEntryList(client.Handle, interfaceInfo.Id); foreach (var networkBssEntry in networkBssEntryList) { //Debug.WriteLine("Interface: {0}, SSID: {1}, BSSID: {2}, Signal: {3} Link: {4}, Frequency: {5}", // interfaceInfo.Description, // networkBssEntry.dot11Ssid, // networkBssEntry.dot11Bssid, // networkBssEntry.lRssi, // networkBssEntry.uLinkQuality, // networkBssEntry.ulChCenterFrequency); yield return(new BssNetworkPack( interfaceInfo: interfaceInfo, ssid: new NetworkIdentifier(networkBssEntry.dot11Ssid.ToBytes(), networkBssEntry.dot11Ssid.ToString()), bssType: ConvertToBssType(networkBssEntry.dot11BssType), bssid: new NetworkIdentifier(networkBssEntry.dot11Bssid.ToBytes(), networkBssEntry.dot11Bssid.ToString()), signalStrength: networkBssEntry.lRssi, linkQuality: (int)networkBssEntry.uLinkQuality, frequency: (int)networkBssEntry.ulChCenterFrequency, channel: DetectChannel(networkBssEntry.ulChCenterFrequency))); } } } }
/// <summary> /// Enumerates wireless LAN information on available networks. /// </summary> /// <returns>Wireless LAN information</returns> /// <remarks>If multiple profiles are associated with a same network, there will be multiple /// entries with the same SSID.</remarks> public static IEnumerable <AvailableNetworkPack> EnumerateAvailableNetworks() { using (var client = new Base.WlanClient()) { var interfaceInfoList = Base.GetInterfaceInfoList(client.Handle); foreach (var interfaceInfo in interfaceInfoList.Select(x => ConvertToInterfaceInfo(x))) { var availableNetworkList = Base.GetAvailableNetworkList(client.Handle, interfaceInfo.Id); foreach (var availableNetwork in availableNetworkList) { //Debug.WriteLine("Interface: {0}, SSID: {1}, Signal: {2}, Security: {3}", // interfaceInfo.Description, // availableNetwork.dot11Ssid, // availableNetwork.wlanSignalQuality, // availableNetwork.bSecurityEnabled); yield return(new AvailableNetworkPack( interfaceInfo: interfaceInfo, ssid: new NetworkIdentifier(availableNetwork.dot11Ssid.ToBytes(), availableNetwork.dot11Ssid.ToString()), bssType: ConvertToBssType(availableNetwork.dot11BssType), signalQuality: (int)availableNetwork.wlanSignalQuality, isSecurityEnabled: availableNetwork.bSecurityEnabled, profileName: availableNetwork.strProfileName)); } } } }
/// <summary> /// Enumerates wireless interface information. /// </summary> /// <returns>Wireless interface information</returns> public static IEnumerable <InterfaceInfo> EnumerateInterfaces() { using (var client = new Base.WlanClient()) { return(Base.GetInterfaceInfoList(client.Handle) .Select(x => ConvertToInterfaceInfo(x))); } }
/// <summary> /// Asynchronously attempts to connect to the wireless LAN associated to a specified wireless profile. /// </summary> /// <param name="interfaceId">Interface ID</param> /// <param name="profileName">Profile name</param> /// <param name="bssType">BSS network type</param> /// <param name="timeout">Timeout duration</param> /// <param name="cancellationToken">Cancellation token</param> /// <returns>True if successfully connected. False if failed or timed out.</returns> public static async Task <bool> ConnectNetworkAsync(Guid interfaceId, string profileName, BssType bssType, TimeSpan timeout, CancellationToken cancellationToken) { if (interfaceId == Guid.Empty) { throw new ArgumentException(nameof(interfaceId)); } if (string.IsNullOrWhiteSpace(profileName)) { throw new ArgumentNullException(nameof(profileName)); } if (timeout < TimeSpan.Zero) { throw new ArgumentException(nameof(timeout)); } using (var client = new Base.WlanClient()) { var tcs = new TaskCompletionSource <bool>(); Action <IntPtr, IntPtr> callback = (data, context) => { var notificationData = Marshal.PtrToStructure <WLAN_NOTIFICATION_DATA>(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; } }; Base.RegisterNotification(client.Handle, WLAN_NOTIFICATION_SOURCE_ACM, callback); var result = Base.Connect(client.Handle, interfaceId, profileName, ConvertFromBssType(bssType)); if (!result) { tcs.SetResult(false); } var connectTask = tcs.Task; var completedTask = await Task.WhenAny(connectTask, Task.Delay(timeout, cancellationToken)); return((completedTask == connectTask) && connectTask.Result); } }
/// <summary> /// Gets a specified wireless profile information. /// </summary> /// <param name="clientHandle">Client handle</param> /// <param name="interfaceInfo">Interface information</param> /// <param name="profileName">Profile name</param> /// <param name="signalQuality">Signal quality</param> /// <param name="position">Position in preference order</param> /// <param name="isConnected">Whether this profile is connected to a wireless LAN</param> /// <returns>Wireless profile information</returns> /// <remarks> /// For profile elements, see /// https://msdn.microsoft.com/en-us/library/windows/desktop/ms707381.aspx /// </remarks> private static ProfilePack GetProfile(SafeClientHandle clientHandle, InterfaceInfo interfaceInfo, string profileName, int signalQuality, int position, bool isConnected) { ProfileType profileType; var source = Base.GetProfile(clientHandle, interfaceInfo.Id, profileName, out profileType); 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 ssidHexadecimalString = ssidXml?.Descendants(ns + "hex").FirstOrDefault()?.Value; var ssidBytes = ConvertFromHexadecimalStringToBytes(ssidHexadecimalString); var ssidString = ssidXml?.Descendants(ns + "name").FirstOrDefault()?.Value; var connectionTypeXml = rootXml.Descendants(ns + "connectionType").FirstOrDefault(); var bssType = ConvertToBssType(connectionTypeXml?.Value); var connectionModeXml = rootXml.Descendants(ns + "connectionMode").FirstOrDefault(); var isAutomatic = (connectionModeXml?.Value.Equals("auto", StringComparison.OrdinalIgnoreCase)).GetValueOrDefault(); var authenticationXml = rootXml.Descendants(ns + "authentication").FirstOrDefault(); var authentication = authenticationXml?.Value; var encryptionXml = rootXml.Descendants(ns + "encryption").FirstOrDefault(); var encryption = encryptionXml?.Value; //Debug.WriteLine("SSID: {0}, BssType: {1}, Authentication: {2}, Encryption: {3}, Automatic: {4}", // ssidString, // bssType, // authentication, // encryption, // isAutomatic); return(new ProfilePack( name: profileName, interfaceInfo: interfaceInfo, profileType: profileType, profileXml: source, ssid: new NetworkIdentifier(ssidBytes, ssidString), bssType: bssType, authentication: authentication, encryption: encryption, signalQuality: signalQuality, position: position, isAutomatic: isAutomatic, isConnected: isConnected)); }
private static bool TurnInterfaceRadio(Guid interfaceId, DOT11_RADIO_STATE radioState) { using (var client = new Base.WlanClient()) { var phyRadioState = new WLAN_PHY_RADIO_STATE { dot11SoftwareRadioState = radioState, }; return(Base.SetPhyRadioState(client.Handle, interfaceId, phyRadioState)); } }
/// <summary> /// Disconnects from the wireless LAN associated to a specified wireless interface. /// </summary> /// <param name="interfaceId">Interface ID</param> /// <returns>True if successfully requested the disconnection. False if failed.</returns> public static bool DisconnectNetwork(Guid interfaceId) { if (interfaceId == Guid.Empty) { throw new ArgumentException(nameof(interfaceId)); } using (var client = new Base.WlanClient()) { return(Base.Disconnect(client.Handle, interfaceId)); } }
/// <summary> /// Enumerates wireless profile information in preference order. /// </summary> /// <returns>Wireless profile information</returns> public static IEnumerable <ProfilePack> EnumerateProfiles() { using (var client = new Base.WlanClient()) { var interfaceInfoList = Base.GetInterfaceInfoList(client.Handle); foreach (var interfaceInfo in interfaceInfoList.Select(x => ConvertToInterfaceInfo(x))) { var interfaceIsConnected = (interfaceInfo.State == InterfaceState.Connected); var availableNetworkList = Base.GetAvailableNetworkList(client.Handle, interfaceInfo.Id) .Where(x => !string.IsNullOrWhiteSpace(x.strProfileName)) .ToArray(); var connection = Base.GetConnectionAttributes(client.Handle, interfaceInfo.Id); var profileInfoList = Base.GetProfileInfoList(client.Handle, interfaceInfo.Id); int position = 0; foreach (var profileInfo in profileInfoList) { var availableNetwork = availableNetworkList.FirstOrDefault(x => x.strProfileName.Equals(profileInfo.strProfileName, StringComparison.Ordinal)); var signalQuality = (int)availableNetwork.wlanSignalQuality; var profileIsConnected = interfaceIsConnected && profileInfo.strProfileName.Equals(connection.strProfileName, StringComparison.Ordinal); //Debug.WriteLine("Interface: {0}, Profile: {1}, Signal {2}, Position: {3}, Connected {4}", // interfaceInfo.Description, // profileInfo.strProfileName, // signalQuality, // position, // profileIsConnected); var profile = GetProfile( client.Handle, interfaceInfo, profileInfo.strProfileName, signalQuality, position++, profileIsConnected); if (profile != null) { yield return(profile); } } } } }
/// <summary> /// Asynchronously requests wireless interfaces to scan (rescan) wireless LANs. /// </summary> /// <param name="timeout">Timeout duration</param> /// <param name="cancellationToken">Cancellation token</param> /// <returns>Interface IDs that successfully scanned</returns> public static async Task <IEnumerable <Guid> > ScanNetworksAsync(TimeSpan timeout, CancellationToken cancellationToken) { using (var client = new Base.WlanClient()) { var interfaceInfoList = Base.GetInterfaceInfoList(client.Handle); var interfaceIds = interfaceInfoList.Select(x => x.InterfaceGuid).ToArray(); var tcs = new TaskCompletionSource <bool>(); var handler = new ScanHandler(tcs, interfaceIds); Action <IntPtr, IntPtr> callback = (data, context) => { var notificationData = Marshal.PtrToStructure <WLAN_NOTIFICATION_DATA>(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: handler.SetSuccess(notificationData.InterfaceGuid); break; case (uint)WLAN_NOTIFICATION_ACM.wlan_notification_acm_scan_fail: handler.SetFailure(notificationData.InterfaceGuid); break; } }; Base.RegisterNotification(client.Handle, WLAN_NOTIFICATION_SOURCE_ACM, callback); foreach (var interfaceId in interfaceIds) { var result = Base.Scan(client.Handle, interfaceId); if (!result) { handler.SetFailure(interfaceId); } } var scanTask = tcs.Task; await Task.WhenAny(scanTask, Task.Delay(timeout, cancellationToken)); return(handler.Results); } }
/// <summary> /// Attempts to connect to the wireless LAN associated to a specified wireless profile. /// </summary> /// <param name="interfaceId">Interface ID</param> /// <param name="profileName">Profile name</param> /// <param name="bssType">BSS network type</param> /// <returns>True if successfully requested the connection. False if failed.</returns> public static bool ConnectNetwork(Guid interfaceId, string profileName, BssType bssType = BssType.Any) { if (interfaceId == Guid.Empty) { throw new ArgumentException(nameof(interfaceId)); } if (string.IsNullOrWhiteSpace(profileName)) { throw new ArgumentNullException(nameof(profileName)); } using (var client = new Base.WlanClient()) { return(Base.Connect(client.Handle, interfaceId, profileName, ConvertFromBssType(bssType))); } }
/// <summary> /// Deletes a specified wireless profile. /// </summary> /// <param name="interfaceId">Interface ID</param> /// <param name="profileName">Profile name</param> /// <returns>True if successfully deleted. False if could not delete.</returns> public static bool DeleteProfile(Guid interfaceId, string profileName) { if (interfaceId == Guid.Empty) { throw new ArgumentException(nameof(interfaceId)); } if (string.IsNullOrWhiteSpace(profileName)) { throw new ArgumentNullException(nameof(profileName)); } using (var client = new Base.WlanClient()) { return(Base.DeleteProfile(client.Handle, interfaceId, profileName)); } }
/// <summary> /// Sets (add or overwrite) the content of a specific profile. /// </summary> /// <param name="interfaceId">Interface ID</param> /// <param name="profileType">Profile type</param> /// <param name="profileXml">Profile XML</param> /// <param name="profileSecurity">Security descriptor for all-user profile</param> /// <param name="overwrite">Whether to overwrite an existing profile</param> /// <returns>True if successfully set. False if not.</returns> /// <remarks> /// 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 /// </remarks> public static bool SetProfile(Guid interfaceId, ProfileType profileType, string profileXml, string profileSecurity, bool overwrite) { if (interfaceId == Guid.Empty) { throw new ArgumentException(nameof(interfaceId)); } if (string.IsNullOrWhiteSpace(profileXml)) { throw new ArgumentNullException(nameof(profileXml)); } using (var client = new Base.WlanClient()) { return(Base.SetProfile(client.Handle, interfaceId, profileType, profileXml, profileSecurity, overwrite)); } }
/// <summary> /// Enumerates wireless profile names in preference order. /// </summary> /// <returns>Wireless profile names</returns> public static IEnumerable <string> EnumerateProfileNames() { using (var client = new Base.WlanClient()) { var interfaceInfoList = Base.GetInterfaceInfoList(client.Handle); foreach (var interfaceInfo in interfaceInfoList) { var profileInfoList = Base.GetProfileInfoList(client.Handle, interfaceInfo.InterfaceGuid); foreach (var profileInfo in profileInfoList) { //Debug.WriteLine("Interface: {0}, Profile: {1}", // interfaceInfo.strInterfaceDescription, // profileInfo.strProfileName); yield return(profileInfo.strProfileName); } } } }
/// <summary> /// Enumerates SSIDs of available wireless LANs. /// </summary> /// <returns>SSIDs</returns> public static IEnumerable <NetworkIdentifier> EnumerateAvailableNetworkSsids() { using (var client = new Base.WlanClient()) { var interfaceInfoList = Base.GetInterfaceInfoList(client.Handle); foreach (var interfaceInfo in interfaceInfoList) { var availableNetworkList = Base.GetAvailableNetworkList(client.Handle, interfaceInfo.InterfaceGuid); foreach (var availableNetwork in availableNetworkList) { //Debug.WriteLine("Interface: {0}, SSID: {1}, Signal: {2}", // interfaceInfo.strInterfaceDescription, // availableNetwork.dot11Ssid, // availableNetwork.wlanSignalQuality); yield return(new NetworkIdentifier(availableNetwork.dot11Ssid.ToBytes(), availableNetwork.dot11Ssid.ToString())); } } } }
/// <summary> /// Sets the position of a specified wireless profile in preference order. /// </summary> /// <param name="interfaceId">Interface ID</param> /// <param name="profileName">Profile name</param> /// <param name="position">Position (starting from 0)</param> /// <returns>True if successfully set.</returns> public static bool SetProfilePosition(Guid interfaceId, string profileName, int position) { if (interfaceId == Guid.Empty) { throw new ArgumentException(nameof(interfaceId)); } if (string.IsNullOrWhiteSpace(profileName)) { throw new ArgumentNullException(nameof(profileName)); } if (position < 0) { throw new ArgumentOutOfRangeException(nameof(position)); } using (var client = new Base.WlanClient()) { return(Base.SetProfilePosition(client.Handle, interfaceId, profileName, (uint)position)); } }