• Developer Network
    • Technologies
      • App Development
      • Cloud
      • Web
      • Data
      • Gaming
      • Internet of Things
    • Downloads
      • Visual Studio
      • MSDN subscription access
      • SDKs
      • Trial software
    • Programs
      • MSDN subscriptions
      • Students
      • Architects
      • ISV
      • Startups
      • TechRewards
      • Events
    • Community
      • Magazine
      • Forums
      • Blogs
      • Tech Advisors
      • Channel 9
    • Documentation
      • APIs and reference
      • Dev centers
    • Samples
Developer Network Developer
Sign in
MSDN subscriptions
Get tools
magazine
  • Issues and downloads
    • All issues
    • 2016
      • July 2016
      • June 2016
      • May 2016
      • April 2016
      • March 2016
      • February 2016
      • January 2016
    • 2015
      • December 2015
      • November 2015
      • Windows 10 issue
      • October 2015
      • September 2015
      • August 2015
      • July 2015
      • June 2015
      • May 2015
      • April 2015
      • March 2015
      • February 2015
      • January 2015
    • 2014
      • Special 2014
      • December 2014
      • November 2014
      • October 2014
      • September 2014
      • August 2014
      • July 2014
      • June 2014
      • May 2014
      • April 2014
      • March 2014
      • February 2014
      • January 2014
    • 2013
      • Government 2013
      • December 2013
      • November 2013
      • October 2013
      • September 2013
      • August 2013
      • July 2013
      • June 2013
      • May 2013
      • April 2013
      • March 2013
      • February 2013
      • January 2013
    • 2012
      • December 2012
      • November 2012
      • Windows 8
      • October 2012
      • September 2012
      • August 2012
      • July 2012
      • June 2012
      • May 2012
      • April 2012
      • March 2012
      • February 2012
      • January 2012
    • 2011
      • December 2011
      • November 2011
      • October 2011
      • September 2011
      • August 2011
      • July 2011
      • June 2011
      • May 2011
      • April 2011
      • March 2011
      • February 2011
      • January 2011
    • 2010
      • December 2010
      • November 2010
      • October 2010
      • September 2010
      • August 2010
      • July 2010
      • June 2010
      • May 2010
      • April 2010
      • March 2010
      • February 2010
      • January 2010
    • 2009
      • December 2009
      • November 2009
      • October 2009
      • September 2009
      • August 2009
      • July 2009
      • June 2009
      • May 2009
      • April 2009
      • March 2009
      • February 2009
      • January 2009
  • Subscribe
  • Submit article
We’re sorry. The content you requested has been removed. You’ll be auto redirected in 1 second.
Issues and downloads 2016 July 2016 Modern Apps - Build a Wi-Fi Scanner in the UWP

July 2016
Volume 31 Number 7

Modern Apps - Build a Wi-Fi Scanner in the UWP

By Frank La Vigne | July 2016 | Get the Code

Wi-Fi has over the last decade or so become ubiquitous. Many shops and cafes offer free Wi-Fi to customers for their convenience. Virtually all hotels offer some kind of wireless Internet to their guests. Most of us have wireless networks at home. As few tablets and mobile devices have Ethernet jacks, Wi-Fi has become integral to our modern lives. Beyond that, we rarely give it much thought.

So, questions abound. What about the sheer volume of Wi-Fi networks around us? How many are there? Are they secured? What channel are they on? What are they named? Can we map them? What can we learn from Wi-Fi network metadata?

While walking my dogs recently, I happened to glance at my phone’s Wi-Fi network connection screen and noticed some witty network names. This got me to wonder how many others had chosen to be comical versus practical. Then, I had the idea to map out and scan wireless networks in and around my neighborhood. If I could automate the process, I could even scan and map wireless networks during my commute to work. Ideally, I could have a program running on a Raspberry Pi that would periodically scan wirelessly and record that data to a Web service. This certainly would be more practical than glancing at my phone intermittently.

As it turns out, the Universal Windows Platform (UWP) provides rich access to wireless network data via classes in the Windows.Devices.WiFi namespace. As you know, a UWP app can run not only on phones and PCs, but on Raspberry Pi 2 running Windows 10 IoT Core. Now, I had all I needed to build out my project.

In this column, I’ll explore the basics of scanning Wi-Fi networks using the APIs built right into the UWP.

Windows.Devices.WiFi Namespace

The classes inside the Windows.Devices.WiFi namespace contain everything needed to scan and explore wireless adapters and wireless networks within range. After creating a new UWP project in Visual Studio, add a new class called WifiScanner and add the following property:

C#
Copy
public WiFiAdapter WiFiAdapter { get; private set; }

Because it’s possible to have multiple Wi-Fi adapters on a given system, you must pick the Wi-Fi adapter you want to use. The InitializeFirstAdapter method gets the first one enumerated in the system, as shown in Figure 1.

Figure 1 Find the First Wi-Fi Adapter Connected to the System and Initialize It
C#
Copy
private async Task InitializeFirstAdapter()
{
  var access = await WiFiAdapter.RequestAccessAsync();
  if (access != WiFiAccessStatus.Allowed)
  {
    throw new Exception("WiFiAccessStatus not allowed");
  }
  else
  {
    var wifiAdapterResults =
      await DeviceInformation.FindAllAsync(WiFiAdapter.GetDeviceSelector());
  if (wifiAdapterResults.Count >= 1)
    {
      this.WiFiAdapter =
        await WiFiAdapter.FromIdAsync(wifiAdapterResults[0].Id);
    }
    else
    {
      throw new Exception("WiFi Adapter not found.");
    }
  }
}

Adding the Wi-Fi Capability

You might notice that there’s a check for access to the Wi-Fi and that the code throws an exception if the RequestAccessAsync method returns false. This is because the app needs to have a device capability to let it scan and connect to Wi-Fi networks. This capability isn’t listed in the Capabilities tab in the manifest properties editor. To add this capability, right-click on the Package.appxmanager file and choose View Code.

You’ll now see the raw XML of the Package.appxmanager file. Inside the Capabilities node, add the following code:

XML
Copy
<DeviceCapability Name="wifiControl" />

Now save the file. Your app now has permission to access the Wi-Fi APIs.

Exploring Wireless Networks

With the code to identify a Wi-Fi adapter to work with and permission to access it, the next step is to actually scan for networks. Fortunately, the code to do that is fairly simple; it’s just a call to the ScanAsync method on the WifiAdapter object. Add the following method to the WifiScanner class:

C#
Copy
public async Task ScanForNetworks()
{
  if (this.WiFiAdapter != null)
  {
    await this.WiFiAdapter.ScanAsync();
  }
  }

Once ScanAsync runs, the NetworkReport property of the WifiAdapter gets populated. NetworkReport is an instance of WiFiNetworkReport, which contains AvailableNetworks, a List<WiFiAvailableNetwork>. The WiFiAvailableNework object contains numerous data points about a given network. You can find the Service Set Identifier (SSID), signal strength, encryption method and access point uptime, among other data points, all without connecting to the network.

Iterating through the available networks is quite easy: You create a Plain Old CLR Object (POCO) to contain some of the data from the WiFiAvailableNetwork objects, as seen in the following code:

C#
Copy
foreach (var availableNetwork in report.AvailableNetworks)
{
  WiFiSignal wifiSignal = new WiFiSignal()
  {
    MacAddress = availableNetwork.Bssid,
    Ssid = availableNetwork.Ssid,
    SignalBars = availableNetwork.SignalBars,
    ChannelCenterFrequencyInKilohertz =
      availableNetwork.ChannelCenterFrequencyInKilohertz,
    NetworkKind = availableNetwork.NetworkKind.ToString(),
    PhysicalKind = availableNetwork.PhyKind.ToString()
  };
}

Building the UI

While I intend for the app to run without a UI in the final project, it’s useful for development and troubleshooting to see the networks within range and the metadata associated with them. It’s also useful for developers who might not have a Raspberry Pi at the moment, but still want to follow along. As shown in Figure 2, the XAML for the project is straightforward and there’s a multiline TextBox to store the output of the scan.

Figure 2 The XAML for the UI
XML
Copy
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
  <Grid.RowDefinitions>
    <RowDefinition Height="60"/>
      <RowDefinition Height="60"/>
      <RowDefinition Height="*"/>
  </Grid.RowDefinitions>
  <TextBlock FontSize="36" Grid.RowSpan="2" >WiFi Scanner</TextBlock>
  <StackPanel Name="spButtons" Grid.Row="1" Orientation="Horizontal">
    <Button Name="btnScan" Click="btnScan_Click" Grid.Row="1">Scan For
      Networks</Button>
  </StackPanel>
  <TextBox Name="txbReport" TextWrapping="Wrap" AcceptsReturn="True"
    Grid.Row="2"></TextBox>
  </Grid>
</Page>

Capturing Location Data

In order to provide additional value, each scan of the wireless network should also note the location of the scan. This will make it possible to provide interesting insights and data visualizations later. Fortunately, adding location to UWP apps is simple. You will, however, need to add the Location capability to your app. You can do that by double-clicking on the Package.appxmanifest file in Solution Explorer, clicking on the Capabilities tab, and checking the Location checkbox in the Capabilities list.

The following code will retrieve the location using the APIs built into the UWP:

C#
Copy
Geolocator geolocator = new Geolocator();
Geoposition position = await geolocator.GetGeopositionAsync();

Now that you have a location, you’ll want to store the location data. Following is the WiFiPointData class, which stores location data along with information about networks found at the location:

C#
Copy
public class WiFiPointData
{
  public DateTimeOffset TimeStamp { get; set; }
  public double Latitude { get; set; }
  public double Longitude { get; set; }
  public double Accuracy { get; set; }
  public List<WiFiSignal> WiFiSignals { get; set; }
  public WiFiPointData()
  {
    this.WiFiSignals = new List<WiFiSignal>();
  }
}

At this time, it’s important to note that unless your device has a GPS device, then the app requires a Wi-Fi connection to the Internet in order to resolve location. Without an onboard GPS sensor, you’ll have to have a mobile hotspot and make sure that your laptop or Raspberry Pi 2 is connected to it. This also means that the reported location will be less accurate. For more information on best practices for creating location-aware UWP, please refer to the Windows Dev Center article, “Guidelines for Location-Aware Apps,” at bit.ly/1P0St0C.

Scanning Repeatedly

For a scanning-and-mapping-while-driving scenario, the app needs to periodically scan for Wi-Fi networks. To accomplish this, you’ll need to use a DispatchTimer to scan for Wi-Fi networks at regular intervals. If you’re not familiar with how DispatchTimer works, please refer to the documentation at bit.ly/1WPMFcp.

It’s important to note that a Wi-Fi scan can take up to several seconds, depending on your system. The following code sets up a DispatchTimer to fire an event every 10 seconds, more than enough time for even the slowest system:

C#
Copy
DispatcherTimer timer = new DispatcherTimer();
timer.Interval = new TimeSpan(0, 0, 10);
timer.Tick += Timer_Tick;
timer.Start();

Every 10 seconds, the timer will run the code in the Timer_Tick method. The following code scans for Wi-Fi networks and then appends the results to the TextBox in the UI:

C#
Copy
private async void Timer_Tick(object sender, object e)
{
  StringBuilder networkInfo = await RunWifiScan();
  this.txbReport.Text = this.txbReport.Text + networkInfo.ToString();
}

Reporting Scan Results

As mentioned previously, once the ScanAsync method is called, the results of the scan are stored in a List<WiFiAvailableNetwork>. All it takes to get to those results is to iterate through the list. The code in Figure 3 does just that and places the results into an instance of the WiFiPointData class.

Figure 3 Code to Iterate Through All the Networks Found During a Scan
C#
Copy
foreach (var availableNetwork in report.AvailableNetworks)
{
  WiFiSignal wifiSignal = new WiFiSignal()
  {
    MacAddress = availableNetwork.Bssid,
    Ssid = availableNetwork.Ssid,
    SignalBars = availableNetwork.SignalBars,
    NetworkKind = availableNetwork.NetworkKind.ToString(),
    PhysicalKind = availableNetwork.PhyKind.ToString(),
    Encryption = availableNetwork.SecuritySettings.NetworkEncryptionType.ToString()
  };
  wifiPoint.WiFiSignals.Add(wifiSignal);
  }

In order to make the UI simple while still providing for rich data analysis, you can convert the WiFiPointData to a Comma Separated Value (CSV) format and set the text of the TextBox in the UI. CSV is a relatively simple format that can be imported into Excel and Power BI for analysis. The code to convert WiFiPointData is shown in Figure 4.

Figure 4 Converting WiFiPointData
C#
Copy
private StringBuilder CreateCsvReport(WiFiPointData wifiPoint)
{
  StringBuilder networkInfo = new StringBuilder();
  networkInfo.AppendLine("MAC,SSID,SignalBars,Type,Lat,Long,Accuracy,Encryption");
  foreach (var wifiSignal in wifiPoint.WiFiSignals)
  {
    networkInfo.Append($"{wifiSignal.MacAddress},");
    networkInfo.Append($"{wifiSignal.Ssid},");
    networkInfo.Append($"{wifiSignal.SignalBars},");
    networkInfo.Append($"{wifiSignal.NetworkKind},");
    networkInfo.Append($"{wifiPoint.Latitude},");
    networkInfo.Append($"{wifiPoint.Longitude},");
    networkInfo.Append($"{wifiPoint.Accuracy},");
    networkInfo.Append($"{wifiSignal.Encryption}");
    networkInfo.AppendLine();
  }
  return networkInfo;
}

Visualizing the Data

Naturally, I couldn’t wait to set up my cloud service to display and visualize the data. Accordingly, I took the CSV data generated by the app and copied and pasted that into a text file. I then made sure to save the file with a .CSV extension. Next, I imported the data into Power BI Desktop. Power BI Desktop is a free download from powerbi.microsoft.com that makes it easy to visualize and explore data.

To import the data from the app, click on Get Data on the Power Bi Desktop splash screen.

On the following screen, choose CSV and then click Connect. In the file picker dialog, choose the CSV file with the data copied and pasted out of the app.

Once that loads, you’ll then see a list of fields on the right hand side of the screen. While a full tutorial on Power BI Desktop is beyond the scope of this article, it doesn’t take much skill to produce a visualization that shows the location of Wi-Fi networks, their SSIDs and the encryption protocols they employ, as shown in Figure 5.

Power BI Visualization of Data the Wi-Fi Scanner App Collected
Figure 5 Power BI Visualization of Data the Wi-Fi Scanner App Collected

Amazingly, about one-third of networks are completely unencrypted. While some of these are guest networks set up at various businesses, some are not.

Practical Applications

While the original intent was merely to measure the technical savvy and wit of my neighbors, this project has some rather interesting practical uses. The ability to easily and automatically map Wi-Fi signal strength and location has interesting applications. What could a city do if each city bus were outfitted with an IoT device with this app running on it? Cities could measure the prevalence of Wi-Fi networks and correlate that data with neighborhood income data. Elected officials could then make informed policy decisions based on that data. If a community provides public Wi-Fi across town or in certain areas, then the signal strength could be measured in real time without the added cost of sending technicians around. Cities could also determine where unsecured networks were prevalent and create targeted awareness programs to increase community cyber security.

On a smaller scale, the ability to quickly scan Wi-Fi network metadata comes in handy when setting up your own network. Many routers offer users the chance to modify the channel on which they broadcast. A great example of this is an app called “Wi-Fi Analyzer” (bit.ly/25ovZ0Q), which, among other things, displays the strength and frequency of nearby wireless networks. This comes in handy when setting up a Wi-Fi network in a new location.

Wrapping Up

Copying and pasting text data from the UI will not scale. Furthermore, if the goal is to run the app on an IoT device without any type of display, then the app needs to send data to the cloud without any UI. In my next month’s column, you’ll learn how to set up a cloud service to take in all this data. Additionally, you’ll learn how to deploy the solution to a Raspberry Pi 2 running Windows IoT Core.


Frank La Vigne is a technology evangelist on the Microsoft Technology and Civic Engagement team, where he helps users leverage technology in order to create a better community. He blogs regularly at FranksWorld.com and has a YouTube channel called Frank’s World TV (youtube.com/FranksWorldTV).

Thanks to the following technical experts for reviewing this article: Rachel Appel, Robert Bernstein and Jose Luis Manners


Discuss this article in the MSDN Magazine forum

Modern Apps - Build a Wi-Fi Scanner in the UWP

In this month’s Modern Apps column, Frank La Vigne explores the basics of scanning Wi-Fi networks using the APIs built into the Universal Windows Platform. Read this article in the July issue of MSDN Magazine

Jul 1, 2016

MSDN Magazine Blog

More MSDN Magazine Blog entries >


Current Issue


July 2016 issue

Browse All MSDN Magazines


Subscribe to the MSDN Flash newsletter Subscribe to MSDN Flash newsletter


Receive the MSDN Flash e-mail newsletter every other week, with news and information personalized to your interests and areas of focus.

Is this page helpful?
Additional feedback?
1500 characters remaining
Thank you! We appreciate your feedback.
Dev centers
  • Windows
  • Office
  • Visual Studio
  • Microsoft Azure
  • More...
Learning resources
  • Microsoft Virtual Academy
  • Channel 9
  • MSDN Magazine
Community
  • Forums
  • Blogs
  • Codeplex
Support
  • Self support
Programs
  • BizSpark (for startups)
  • DreamSpark
  • Imagine Cup
United States (English)
  • Newsletter
  • Privacy & cookies
  • Terms of use
  • Trademarks
© 2016 Microsoft