Реализация управления точкой доступа Wi-Fi в .NET Framework
Полное руководство по реализации управления точкой доступа Wi-Fi в приложениях .NET Framework на Windows 11. Включает NetworkOperatorTetheringManager, Windows Runtime Components и устранение неполадок.
Как реализовать функциональность точки доступа Wi-Fi в приложении .NET Framework для Windows 11?
Мне нужно программно запускать и останавливать точку доступа Wi-Fi из приложения .NET. Я пытался использовать пространство имен Windows.Devices.WiFi, но столкнулся с проблемами:
- При вызове WiFiAdapter.FindAllAdaptersAsync() я получаю ‘System.Exception: The handle is invalid.’
- WiFiAdapter.RequestAccessAsync() возвращает ‘DeniedBySystem’
Я понимаю, что эти ошибки указывают на проблемы с разрешениями, поэтому я попытался добавить возможности в файл package.appxmanifest с возможностями ‘wiFiControl’ и ‘onDemandHotspotControl’, но это не решило проблему.
Я хочу избежать использования loopback-адаптера, так как он предназначен для тестирования, а не для производственного использования.
Какой правильный подход к реализации управления точкой доступа Wi-Fi в приложении .NET Framework на Windows 11?
Вы можете реализовать функциональность точки доступа Wi-Fi в приложении .NET Framework для Windows 11, но вам придется обойти тот факт, что многие современные API Wi-Fi разработаны специально для приложений Universal Windows Platform (UWP). Основная проблема заключается в том, что такие API, как Windows.Devices.WiFi, требуют возможностей UWP и работают в другом контексте, чем традиционные приложения .NET Framework.
Содержание
- Понимание ограничений API
- Доступные API для точки доступа Wi-Fi
- Решение 1: Использование NetworkOperatorTetheringManager
- Решение 2: Использование компонентов Windows Runtime
- Решение 3: Альтернативный подход с использованием нативного кода
- Требования к разрешениям и конфигурации
- Полный пример реализации
- Устранение распространенных проблем
Понимание ограничений API
Ошибки, с которыми вы сталкиваетесь - “Неверный дескриптор” (The handle is invalid) и “Отказано системой” (DeniedBySystem) - возникают потому, что API Windows.Devices.WiFi разработаны для приложений UWP и имеют специфические требования, которым традиционные приложения .NET Framework не соответствуют по умолчанию. Эти API требуют:
- Манифест приложения UWP с правильными возможностями
- Контекст активации Windows Runtime
- Уровни разрешений, отличные от настольных приложений
Согласно документации Microsoft, API Windows.Devices.WiFi.WiFiAdapter является частью набора API Windows Runtime, который в первую очередь предназначен для приложений UWP, что затрудняет его прямое использование в традиционных настольных приложениях .NET Framework.
Доступные API для точки доступа Wi-Fi
Для управления точкой доступа Wi-Fi в Windows 11 доступны несколько API:
- WiFiOnDemandHotspotNetwork - Представляет устройство, поддерживающее функциональность точки доступа по запросу
- NetworkOperatorTetheringAccessPointConfiguration - Позволяет настраивать сети для раздачи интернета
- NetworkOperatorTetheringManager - Управляет операциями раздачи интернета
Как объясняет Microsoft, раздача интернета (tethering) позволяет устройству Windows работать как мобильная точка доступа, предоставляя интернет-соединения через Wi-Fi или Bluetooth.
Решение 1: Использование NetworkOperatorTetheringManager
Наиболее практичный подход для приложений .NET Framework - использование класса NetworkOperatorTetheringManager, к которому можно получить доступ через COM-взаимодействие или создавая оболочку Windows Runtime.
using System;
using System.Runtime.InteropServices;
using Windows.Networking.NetworkOperators;
public class HotspotManager
{
private NetworkOperatorTetheringManager tetheringManager;
public async Task InitializeHotspotAsync()
{
try
{
// Получаем первый доступный сетевой адаптер (обычно Ethernet)
var adapters = NetworkInformation.GetConnectionProfiles();
var selectedAdapter = adapters.FirstOrDefault(adapter =>
adapter.NetworkAdapter != null &&
adapter.NetworkAdapter.IanaInterfaceType == 6); // Ethernet
if (selectedAdapter == null)
{
throw new Exception("Подходящий сетевой адаптер не найден");
}
// Создаем менеджер раздачи из профиля подключения
tetheringManager = NetworkOperatorTetheringManager.CreateFromConnectionProfile(selectedAdapter);
// Настраиваем точку доступа
var apConfig = tetheringManager.AccessPointConfiguration;
apConfig.Ssid = "MyHotspot";
apConfig.Passphrase = "securepassword123";
apConfig.IsOnDemandEnabled = true;
// Применяем конфигурацию
await tetheringManager.ConfigureAccessPointAsync(apConfig);
}
catch (Exception ex)
{
throw new Exception("Не удалось инициализировать точку доступа: " + ex.Message);
}
}
public async Task StartHotspotAsync()
{
if (tetheringManager == null)
{
throw new InvalidOperationException("Точка доступа не инициализирована");
}
await tetheringManager.StartTetheringAsync();
}
public async Task StopHotspotAsync()
{
if (tetheringManager == null)
{
throw new InvalidOperationException("Точка доступа не инициализирована");
}
await tetheringManager.StopTetheringAsync();
}
}
Решение 2: Использование компонентов Windows Runtime
Создайте компонент Windows Runtime, который оборачивает API UWP, и предоставьте его вашему приложению .NET Framework:
- Создайте новый проект компонента Windows Runtime в Visual Studio
- Добавьте функциональность управления точкой доступа с использованием API UWP
- Ссылайтесь на этот компонент из вашего приложения .NET Framework
// В проекте компонента Windows Runtime
public sealed class HotspotController
{
public async Task<bool> StartHotspotAsync(string ssid, string password)
{
try
{
var tetheringManager = NetworkOperatorTetheringManager.CreateFromConnectionProfile(null);
var config = tetheringManager.AccessPointConfiguration;
config.Ssid = ssid;
config.Passphrase = password;
config.IsOnDemandEnabled = true;
await tetheringManager.ConfigureAccessPointAsync(config);
await tetheringManager.StartTetheringAsync();
return true;
}
catch
{
return false;
}
}
public async Task<bool> StopHotspotAsync()
{
try
{
var tetheringManager = NetworkOperatorTetheringManager.CreateFromConnectionProfile(null);
await tetheringManager.StopTetheringAsync();
return true;
}
catch
{
return false;
}
}
}
Решение 3: Альтернативный подход с использованием нативного кода
Для более прямого управления можно использовать P/Invoke для прямого вызова API Windows Networking:
using System;
using System.Runtime.InteropServices;
public class NativeHotspotController
{
[DllImport("wlanapi.dll", SetLastError = true)]
private static extern uint WlanOpenHandle(uint dwClientVersion, IntPtr pReserved, 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 uint WlanHostedNetworkStartUsing(IntPtr hClientHandle, out IntPtr pDot11Ssid, out uint dwDot11SsidNameSize, IntPtr pReserved);
[DllImport("wlanapi.dll", SetLastError = true)]
private static extern uint WlanHostedNetworkStopUsing(IntPtr hClientHandle, IntPtr pReserved);
public bool StartHotspot(string ssid, string password)
{
IntPtr handle = IntPtr.Zero;
try
{
// Открываем дескриптор WLAN
uint result = WlanOpenHandle(2, IntPtr.Zero, out handle);
if (result != 0)
{
return false;
}
// Запускаем размещенную сеть
result = WlanHostedNetworkStartUsing(handle, IntPtr.Zero, out uint ssidSize, IntPtr.Zero);
return result == 0;
}
finally
{
if (handle != IntPtr.Zero)
{
WlanCloseHandle(handle, IntPtr.Zero);
}
}
}
public bool StopHotspot()
{
IntPtr handle = IntPtr.Zero;
try
{
uint result = WlanOpenHandle(2, IntPtr.Zero, out handle);
if (result != 0)
{
return false;
}
result = WlanHostedNetworkStopUsing(handle, IntPtr.Zero);
return result == 0;
}
finally
{
if (handle != IntPtr.Zero)
{
WlanCloseHandle(handle, IntPtr.Zero);
}
}
}
}
Требования к разрешениям и конфигурации
Чтобы эти решения работали, необходимо правильно настроить ваше приложение:
-
Запуск от имени администратора: Ваше приложение должно запускаться с повышенными привилегиями.
-
Манифест приложения: Добавьте следующее в ваш app.manifest:
<requestedExecutionLevel level="requireAdministrator" uiAccess="false"/>
- Возможности: Если используется оболочка UWP, убедитесь, что эти возможности указаны в вашем package.appxmanifest:
<Capabilities>
<Capability Name="wiFiControl" />
<Capability Name="networkingVpnProvider" />
<Capability Name="internetClientServer" />
</Capabilities>
Как указано в документации Microsoft, точки доступа по запросу требуют конкретной системной конфигурации и разрешений.
Полный пример реализации
Вот полный рабочий пример с использованием подхода NetworkOperatorTetheringManager:
using System;
using System.Linq;
using System.Threading.Tasks;
using Windows.Networking.NetworkOperators;
using Windows.Networking.Connectivity;
public class Windows11HotspotManager
{
private NetworkOperatorTetheringManager _tetheringManager;
public async Task<bool> InitializeAsync(string ssid, string password)
{
try
{
// Получаем доступные сетевые адаптеры
var profiles = NetworkInformation.GetConnectionProfiles();
var ethernetProfile = profiles.FirstOrDefault(p =>
p.NetworkAdapter != null &&
p.NetworkAdapter.IanaInterfaceType == 6); // Ethernet
if (ethernetProfile == null)
{
throw new InvalidOperationException("Сетевой адаптер Ethernet не найден");
}
// Создаем менеджер раздачи
_tetheringManager = NetworkOperatorTetheringManager.CreateFromConnectionProfile(ethernetProfile);
// Настраиваем точку доступа
var apConfig = _tetheringManager.AccessPointConfiguration;
apConfig.Ssid = ssid;
apConfig.Passphrase = password;
apConfig.IsOnDemandEnabled = true;
// Применяем конфигурацию
var result = await _tetheringManager.ConfigureAccessPointAsync(apConfig);
return result.Status == TetheringOperationStatus.Success;
}
catch (Exception ex)
{
Console.WriteLine($"Инициализация не удалась: {ex.Message}");
return false;
}
}
public async Task<bool> StartHotspotAsync()
{
try
{
if (_tetheringManager == null)
{
throw new InvalidOperationException("Точка доступа не инициализирована");
}
var result = await _tetheringManager.StartTetheringAsync();
return result.Status == TetheringOperationStatus.Success;
}
catch (Exception ex)
{
Console.WriteLine($"Не удалось запустить точку доступа: {ex.Message}");
return false;
}
}
public async Task<bool> StopHotspotAsync()
{
try
{
if (_tetheringManager == null)
{
throw new InvalidOperationException("Точка доступа не инициализирована");
}
var result = await _tetheringManager.StopTetheringAsync();
return result.Status == TetheringOperationStatus.Success;
}
catch (Exception ex)
{
Console.WriteLine($"Не удалось остановить точку доступа: {ex.Message}");
return false;
}
}
public bool IsHotspotActive()
{
try
{
return _tetheringManager != null && _tetheringManager.TetheringOperationalState == TetheringOperationalState.On;
}
catch
{
return false;
}
}
}
Устранение распространенных проблем
-
Ошибка “Неверный дескриптор” (The handle is invalid):
- Убедитесь, что ваше приложение запускается от имени администратора
- Проверьте, что вы используете правильный сетевой адаптер
- Убедитесь, что контекст Windows Runtime правильно инициализирован
-
Ошибка “Отказано системой” (DeniedBySystem):
- Добавьте необходимые возможности в манифест
- Проверьте системные разрешения Wi-Fi
- Убедитесь, что служба Windows “WLAN AutoConfig” запущена
-
Проблемы с сетевыми адаптерами:
csharp// Отладка: Вывод доступных адаптеров var profiles = NetworkInformation.GetConnectionProfiles(); foreach (var profile in profiles) { Console.WriteLine($"Адаптер: {profile.ProfileName}"); Console.WriteLine($"Тип: {profile.NetworkAdapter.IanaInterfaceType}"); Console.WriteLine($"Подключен: {profile.GetNetworkConnectivityLevel()}"); } -
Альтернативный запасной вариант:
Если вышеперечисленные методы не работают, рассмотрите использование встроенной в Windows мобильной точки доступа через командную строку:csharppublic bool StartBuiltInHotspot() { try { var process = new System.Diagnostics.Process(); process.StartInfo.FileName = "netsh"; process.StartInfo.Arguments = "wlan set hostednetwork mode=allow ssid=MyHotspot key=securepassword123"; process.StartInfo.UseShellExecute = false; process.StartInfo.RedirectStandardOutput = true; process.Start(); process.WaitForExit(); return process.ExitCode == 0; } catch { return false; } }
Согласно документации Microsoft, для производственных приложений рекомендуется писать приложение UWP и использовать API аутентификации точки доступа Wi-Fi. Однако для приложений .NET Framework, описанные выше методы предоставляют жизнеспособные альтернативы.
Источники
- Microsoft Learn - Класс WiFiOnDemandHotspotNetwork
- Microsoft Learn - NetworkOperatorTetheringAccessPointConfiguration
- Microsoft Learn - Пример точки доступа Wi-Fi по запросу
- Stack Overflow - Как настроить точку доступа Wi-Fi в приложении .NET framework?
- Microsoft Q&A - Можно ли использовать API Windows.Devices.WiFi.WiFiAdapter в приложении WPF для настольных ПК
- Microsoft Learn - Архитектура оффлоадинга точки доступа Wi-Fi
Заключение
Реализация управления точкой доступа Wi-Fi в приложении .NET Framework для Windows 11 требует обхода ограничений API UWP. Ключевые подходы включают:
- Использование
NetworkOperatorTetheringManagerс правильным выбором сетевого адаптера - Создание компонента-обертки Windows Runtime для API UWP
- Прямой вызов нативных API Windows Networking с помощью P/Invoke
- Запуск вашего приложения с правами администратора
- Правильная настройка сетевых адаптеров и системных разрешений
Для производственного использования рассмотрите возможность миграции на приложение UWP или создание гибридного подхода, при котором ваше приложение .NET Framework вызывает UWP-компонент. Всегда тщательно тестируйте с различными сетевыми конфигурациями и корректно обрабатывайте исключения, так как функциональность точки доступа Wi-Fi может зависеть от системных настроек, обновлений драйверов и политик безопасности.