ManagedNativeWifi

repository·master·Indexed 41 days ago

https://github.com/emoacht/managednativewifi

A managed implementation of the Windows Native Wifi API for .NET applications. It provides functionality to manage wireless networks, interfaces, and profiles, including methods to enumerate available SSIDs, connect to networks asynchronously, scan for LANs, and retrieve real-time connection quality on Windows 11 24H2. Supports .NET 8.0 and .NET Standard 2.0 (including .NET Framework 4.6.1).

Tokens
4.9K
Snippets
11
Records
15
Agent score
1%

What's inside ManagedNativeWifi

  1. WPA3 Authentication and Deprecation

    master

    As of version 2.7, WPA3 has been re-designated to support modern security standards. The original WPA3 designation is deprecated and has been superseded by specific Enterprise modes. Use the following mappings for authentication:

    AuthenticationAuthenticationAlgorithmAuthenticationMethod
    WPA3 Enterprise 192-bit modeWPA3_ENT_192WPA3_Enterprise_192
    WPA3 EnterpriseWPA3_ENTWPA3_Enterprise
    OWEOWEOWE

    Version 2.7.1 also included a fix to ensure WPA3 Enterprise is correctly assigned.

  2. Requirements for ManagedNativeWifi

    master

    ManagedNativeWifi is designed for Windows and supports the following runtimes:

    • .NET 8.0
    • .NET Standard 2.0 (including .NET Framework 4.6.1)

    Windows 11 (24H2) Permissions

    On Windows 11 (version 24H2) or newer, certain methods require user permission to access location information. If permission is not granted, an UnauthorizedAccessException will be thrown. You can manage this in: Privacy & security > Location settings.

  3. Migrate to Managed Native Wifi v3.0.1 breaking changes

    master

    If you are upgrading to version 3.0.1, be aware of the following breaking changes that affect existing code:

    • InterfaceConnectionInfo: The ConnectionMode and ProfileName properties have been removed. To retrieve this information, use the GetCurrentConnection method instead.
    • ScanMode Enum: The value OnlyDisconnectd has been renamed to OnlyNotConnected.
    • BssNetworkPack: The SignalStrength property has been renamed to Rssi. This affects the output of EnumerateBssNetworks.
    • Radio Management Methods: The following methods have been renamed:
      • GetInterfaceRadio $\rightarrow$ GetRadio
      • TurnOnInterfaceRadio $\rightarrow$ TurnOnRadio
      • TurnOffInterfaceRadio $\rightarrow$ TurnOffRadio
    • AutoConfig: IsInterfaceAutoConfig is the current name (previously IsInterfaceAutoConfig in older versions, but note the specific renaming history).
    • RadioInfo: The Id property has been removed. This affects the return of GetRadio.
    • Radio State: RadioSet and PhyRadioStateInfo have been replaced by RadioStateSet. This affects both GetRadio and the RadioStateChangedEventArgs event arguments.
    • Connection Methods: The type of the bssid parameter in ConnectNetwork and ConnectNetworkAsync has changed.
  4. Enumerate used wireless LAN channels

    master

    To identify which wireless LAN channels are currently being used by surrounding access points, use NativeWifi.EnumerateBssNetworks() and filter the results by RSSI.

    public static IEnumerable<int> EnumerateNetworkChannels(int rssiThreshold)
    {
        return NativeWifi.EnumerateBssNetworks()
            .Where(x => x.Rssi > rssiThreshold)
            .Select(x => x.Channel);
    }
  5. Enumerate available network SSIDs

    master

    To retrieve a list of SSIDs for currently available wireless LANs, use NativeWifi.EnumerateAvailableNetworkSsids().

    Note: SSIDs are typically represented as UTF-8 strings. If ToString() does not produce a valid value, use the ToBytes() method instead.

    public static IEnumerable<string> EnumerateNetworkSsids()
    {
        return NativeWifi.EnumerateAvailableNetworkSsids()
            .Select(x => x.ToString()); // UTF-8 string representation
    }
  6. Retrieve detailed connection information

    master

    To get information about currently connected wireless interfaces, use the following methods depending on your requirements:

    1. NativeWifi.GetCurrentConnection(interfaceId): Returns general connection details like SSID, PHY type, authentication, cipher, signal quality, and Rx/Tx rates.
    2. NativeWifi.GetRealtimeConnectionQuality(interfaceId): Requires Windows 11 24H2. Provides real-time metrics like link quality, MLO (Multi-Link Operation) status, and detailed link information (RSSI, Frequency, Bandwidth).
    3. NativeWifi.GetRssi(interfaceId): A fallback to get the RSSI if GetRealtimeConnectionQuality is not supported.

    Note: All these methods return a tuple containing an ActionResult. If the interface is not connected, the result will be ActionResult.NotConnected.

    public static void ShowConnectedNetworkInformation()
    {
        foreach (var interfaceId in NativeWifi.EnumerateInterfaces()
            .Where(x => x.State is InterfaceState.Connected)
            .Select(x => x.Id))
        {
            // Get general connection info
            var (result, cc) = NativeWifi.GetCurrentConnection(interfaceId);
            if (result is ActionResult.Success)
            {
                Trace.WriteLine($"SSID: {cc.Ssid}");
                Trace.WriteLine($"Signal quality: {cc.SignalQuality}");
            }
    
            // Get real-time quality (Windows 11 24H2+)
            (result, var rcq) = NativeWifi.GetRealtimeConnectionQuality(interfaceId);
            if (result is ActionResult.Success)
            {
                Trace.WriteLine($"Link quality: {rcq.LinkQuality}");
                if (rcq.Links.Count > 0)
                {
                    Trace.WriteLine($"RSSI: {rcq.Links[0].Rssi}");
                }
            }
            else if (result is ActionResult.NotSupported)
            {
                // Fallback to RSSI
                (result, int rssi) = NativeWifi.GetRssi(interfaceId);
                if (result is ActionResult.Success)
                {
                    Trace.WriteLine($"RSSI: {rssi}");
                }
            }
        }
    }
  7. Turn on the wireless radio

    master

    To enable the wireless radio, first check the current state using NativeWifi.GetRadio, then call NativeWifi.TurnOnRadio.

    Limitations:

    • This method only changes the software radio state.
    • If the hardware radio state is off (e.g., a physical Wi-Fi switch is off), the radio cannot be turned on programmatically.
    • Calling this may throw an UnauthorizedAccessException if permissions are insufficient.
    public static async Task<bool> TurnOnAsync()
    {
        var targetInterface = NativeWifi.EnumerateInterfaces()
            .FirstOrDefault(x =>
            {
                var radioState = NativeWifi.GetRadio(x.Id)?.RadioStates.FirstOrDefault();
                if (radioState is null) return false;
                if (!radioState.IsHardwareOn) return false;
                return !radioState.IsSoftwareOn;
            });
    
        if (targetInterface is null) return false;
    
        try
        {
            return await Task.Run(() => NativeWifi.TurnOnRadio(targetInterface.Id));
        }
        catch (UnauthorizedAccessException)
        {
            return false;
        }
    }
  8. Refresh available wireless LANs

    master

    To trigger a scan for available wireless LANs, use NativeWifi.ScanNetworksAsync. This method requests wireless interfaces to scan in parallel.

    Best Practices:

    • The timeout should ideally be no more than 4 seconds, though it can vary.
    • To avoid disrupting existing wireless connections, use the overload with ScanMode.OnlyNotConnected.
    • If all wireless interfaces are already connected, the scan will not produce new results.
    // Standard refresh
    public static Task RefreshAsync()
    {
        return NativeWifi.ScanNetworksAsync(timeout: TimeSpan.FromSeconds(10));
    }
    
    // Refresh without disrupting existing connections
    public static Task RefreshNotConnectedAsync()
    {
        return NativeWifi.ScanNetworksAsync(
            mode: ScanMode.OnlyNotConnected,
            null,
            null,
            timeout: TimeSpan.FromSeconds(10),
            CancellationToken.None);
    }
  9. Enumerate available networks and signal quality

    master

    To check SSID, signal quality, or other information for available wireless LANs, use NativeWifi.EnumerateAvailableNetworks().

    public static IEnumerable<(string ssidString, int signalQuality)>
        EnumerateNetworkSsidsAndSignalQualities()
    {
        return NativeWifi.EnumerateAvailableNetworks()
            .Select(x => (x.Ssid.ToString(), x.SignalQuality));
    }
  10. Delete a wireless profile

    master

    Use NativeWifi.DeleteProfile to remove an existing wireless profile.

    Important: Profile names are case-sensitive.

    public static bool DeleteProfile(string profileName)
    {
        var targetProfile = NativeWifi.EnumerateProfiles()
            .Where(x => profileName.Equals(x.Name, StringComparison.Ordinal))
            .FirstOrDefault();
    
        if (targetProfile is null)
            return false;
    
        return NativeWifi.DeleteProfile(
            interfaceId: targetProfile.InterfaceInfo.Id,
            profileName: profileName);
    }
  11. Connect to a wireless LAN asynchronously

    master

    Use NativeWifi.ConnectNetworkAsync to connect to a wireless network.

    Unlike the synchronous ConnectNetwork method (which only indicates if the request succeeded), ConnectNetworkAsync returns true only if the connection is successfully established.

    Required parameters:

    • interfaceId: The ID of the wireless interface.
    • profileName: The name of the wireless profile.
    • bssType: The BSS type.
    • timeout: A TimeSpan for the connection attempt.
    public static async Task<bool> ConnectAsync()
    {
        var availableNetwork = NativeWifi.EnumerateAvailableNetworks()
            .Where(x => !string.IsNullOrWhiteSpace(x.ProfileName))
            .OrderByDescending(x => x.SignalQuality)
            .FirstOrDefault();
    
        if (availableNetwork is null)
            return false;
    
        return await NativeWifi.ConnectNetworkAsync(
            interfaceId: availableNetwork.InterfaceInfo.Id,
            profileName: availableNetwork.ProfileName,
            bssType: availableNetwork.BssType,
            timeout: TimeSpan.FromSeconds(10));
    }