Skip to content

Commit f0cf8fe

Browse files
authored
Feature: Request WiFi access (BornToBeRoot#2719)
* Feature: Request WiFi access * Feature: Improve WiFi adapter search * Fix: Catch exception and log it * Docs: BornToBeRoot#2719
1 parent 5258d57 commit f0cf8fe

8 files changed

Lines changed: 988 additions & 873 deletions

File tree

Source/NETworkManager.Localization/Resources/Strings.Designer.cs

Lines changed: 13 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Source/NETworkManager.Localization/Resources/Strings.resx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3823,4 +3823,11 @@ Try again in a few seconds.</value>
38233823
<data name="ExpandAndOpenSearchDots" xml:space="preserve">
38243824
<value>Expand and open search...</value>
38253825
</data>
3826+
<data name="WiFiAccessNotAvailableMessage" xml:space="preserve">
3827+
<value>Access to the Wi-Fi adapter is not permitted by Windows.
3828+
3829+
Open the Windows settings and allow Wi-Fi access for this application.
3830+
3831+
Restart the application afterwards to use this feature.</value>
3832+
</data>
38263833
</root>

Source/NETworkManager.Models/Network/WiFi.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public static class WiFi
2828
/// </returns>
2929
public static async Task<List<WiFiAdapterInfo>> GetAdapterAsync()
3030
{
31-
List<WiFiAdapterInfo> wifiAdapterInfos = new();
31+
List<WiFiAdapterInfo> wifiAdapterInfos = [];
3232

3333
var wifiAdapters = await WiFiAdapter.FindAllAdaptersAsync();
3434

Source/NETworkManager/MainWindow.xaml.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -477,7 +477,7 @@ public MainWindow()
477477

478478
EventSystem.OnRedirectDataToApplicationEvent += EventSystem_RedirectDataToApplicationEvent;
479479
EventSystem.OnRedirectToSettingsEvent += EventSystem_RedirectToSettingsEvent;
480-
480+
481481
_isLoading = false;
482482
}
483483

Source/NETworkManager/ViewModels/WiFiViewModel.cs

Lines changed: 80 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,18 @@
33
using System.Collections.Generic;
44
using System.Collections.ObjectModel;
55
using System.ComponentModel;
6-
using System.IO;
76
using System.Linq;
87
using System.Threading.Tasks;
98
using System.Windows.Data;
109
using System.Windows.Input;
1110
using System.Windows.Threading;
1211
using Windows.Devices.WiFi;
12+
using Windows.Foundation.Metadata;
1313
using Windows.Security.Credentials;
14+
using Windows.System;
1415
using LiveCharts;
1516
using LiveCharts.Wpf;
17+
using log4net;
1618
using MahApps.Metro.Controls.Dialogs;
1719
using NETworkManager.Localization;
1820
using NETworkManager.Localization.Resources;
@@ -28,24 +30,40 @@ namespace NETworkManager.ViewModels;
2830
public class WiFiViewModel : ViewModelBase
2931
{
3032
#region Variables
31-
3233
private readonly IDialogCoordinator _dialogCoordinator;
3334

35+
private static readonly ILog Log = LogManager.GetLogger(typeof(WiFiViewModel));
36+
3437
private readonly bool _isLoading;
3538
private readonly DispatcherTimer _autoRefreshTimer = new();
3639
private readonly DispatcherTimer _hideConnectionStatusMessageTimer = new();
3740

38-
private bool _sdkContractsFailedToLoad;
41+
private bool _sdkContractAvailable;
42+
43+
public bool SdkContractAvailable
44+
{
45+
get => _sdkContractAvailable;
46+
set
47+
{
48+
if (value == _sdkContractAvailable)
49+
return;
50+
51+
_sdkContractAvailable = value;
52+
OnPropertyChanged();
53+
}
54+
}
55+
56+
private bool _wiFiAdapterAccessEnabled;
3957

40-
public bool SdkContractsFailedToLoad
58+
public bool WiFiAdapterAccessEnabled
4159
{
42-
get => _sdkContractsFailedToLoad;
60+
get => _wiFiAdapterAccessEnabled;
4361
set
4462
{
45-
if (value == _sdkContractsFailedToLoad)
63+
if (value == _wiFiAdapterAccessEnabled)
4664
return;
4765

48-
_sdkContractsFailedToLoad = value;
66+
_wiFiAdapterAccessEnabled = value;
4967
OnPropertyChanged();
5068
}
5169
}
@@ -398,6 +416,26 @@ public WiFiViewModel(IDialogCoordinator instance)
398416

399417
_dialogCoordinator = instance;
400418

419+
// Check if Microsoft.Windows.SDK.Contracts is available
420+
SdkContractAvailable = ApiInformation.IsTypePresent("Windows.Devices.WiFi.WiFiAdapter");
421+
422+
if (!SdkContractAvailable)
423+
{
424+
_isLoading = false;
425+
426+
return;
427+
}
428+
429+
// Check if the access is denied and show a message
430+
WiFiAdapterAccessEnabled = RequestAccess();
431+
432+
if (!WiFiAdapterAccessEnabled)
433+
{
434+
_isLoading = false;
435+
436+
return;
437+
}
438+
401439
// Result view + search
402440
NetworksView = CollectionViewSource.GetDefaultView(Networks);
403441
NetworksView.SortDescriptions.Add(new SortDescription(
@@ -504,33 +542,54 @@ private void ExportAction()
504542
Export().ConfigureAwait(false);
505543
}
506544

545+
public ICommand OpenSettingsCommand => new RelayCommand(_ => OpenSettingsAction());
546+
547+
private static void OpenSettingsAction()
548+
{
549+
Launcher.LaunchUriAsync(new Uri("ms-settings:privacy-location"));
550+
}
507551
#endregion
508552

509553
#region Methods
510554

555+
/// <summary>
556+
/// Request access to the WiFi adapter.
557+
/// </summary>
558+
/// <returns>Fails if the access is denied.</returns>
559+
private static bool RequestAccess()
560+
{
561+
var accessStatus = WiFiAdapter.RequestAccessAsync().GetAwaiter().GetResult();
562+
563+
return accessStatus == WiFiAccessStatus.Allowed;
564+
}
565+
511566
private async Task LoadAdapters(string adapterId = null)
512567
{
513568
IsAdaptersLoading = true;
514569

570+
// Show a loading animation for the user
571+
await Task.Delay(2500);
572+
515573
try
516574
{
517575
Adapters = await WiFi.GetAdapterAsync();
518-
519-
// Check if we found any adapters
520-
if (Adapters.Count > 0)
521-
{
522-
// Check for existing adapter id or select the first one
523-
if (string.IsNullOrEmpty(adapterId))
524-
SelectedAdapter = Adapters.FirstOrDefault();
525-
else
526-
SelectedAdapter = Adapters.FirstOrDefault(s => s.NetworkInterfaceInfo.Id.ToString() == adapterId) ??
527-
Adapters.FirstOrDefault();
528-
}
529576
}
530-
catch
531-
(FileNotFoundException) // This exception is thrown, when the Microsoft.Windows.SDK.Contracts is not available...
577+
catch (Exception ex)
532578
{
533-
SdkContractsFailedToLoad = true;
579+
Log.Error("Error trying to get WiFi adapters.", ex);
580+
581+
Adapters.Clear();
582+
}
583+
584+
// Check if we found any adapters
585+
if (Adapters.Count > 0)
586+
{
587+
// Check for existing adapter id or select the first one
588+
if (string.IsNullOrEmpty(adapterId))
589+
SelectedAdapter = Adapters.FirstOrDefault();
590+
else
591+
SelectedAdapter = Adapters.FirstOrDefault(s => s.NetworkInterfaceInfo.Id.ToString() == adapterId) ??
592+
Adapters.FirstOrDefault();
534593
}
535594

536595
IsAdaptersLoading = false;

0 commit comments

Comments
 (0)