WLAN Programming How-To Tips and Tricks Including Using It in C#
Questions concerning the wireless local area network APIs have been coming up a lot recently often in the context of using them from C#. You'll find an example C# WinForms application that allows you to see the almost all of the wireless network APIs in action at the end of this post. The WLAN APIs facilitate the enumeration, configuration, and management of WiFi on Windows Operating Systems. Here are just a fraction of things that the WLAN APIs allow a developer to do programmatically:
- Connect to a wireless network
- Disconnect from a wireless network
- Modify the behavior of the automatic wireless configuration module
- Start or stop a locally hosted wireless network
- Connect to or disconnect from a WiFi Direct device
- Query the properties of any of the above
- Read, Modify, and Create profiles that control the settings for a wireless network
- Create temporary profiles that can be used without making them available for display to the end user
The WLAN APIs follow the same general pattern of proper use for regular WiFi, WiFi Direct, and hosted wireless networks shown here:
- A handle/session is opened using WlanOpenHandle.
- Operations are performed as desired for the specific technology or technologies.
- The opened handle/session is closed using WlanCloseHandle.
The rest of this post is going to focus on the APIs for wireless networks. If you're interested in hearing more about the other technologies, please let me know in the comments section at the bottom of the page. Wireless networks are interacted with using a specific interface which typically ultimately represents a piece of hardware such as a wireless networking card. A collection of wireless network interfaces is obtained through the use of the WlanEnumInterfaces function. Most subsequent operations, such as managing profiles, connect or disconnecting from networks, etc. are performed against one of the specific interfaces. The one real exception is change monitoring. Change monitoring takes places for everything at the session/handle level. All of this functionality lends itself to wrap pretty easily into managed objects. You'll find the specific implementation details of what is below in the example code, but here's a basic summary of how things would roughly shape out as objects taken from the implementation of the example code:
WlanNative - Class that encapsulates the session/handle, provides access to a collection of WlanNativeInterface objects, controls whether or not to be listening for changes, and provides an event that can be subscribed to in order to receive change notifications
WlanNativeInterface - Class that encapsulates a specific wireless interface
Methods: Scan for available wireless networks, connect to a wireless network using an existing or temporary profile, disconnect from a wireless network, retrieve a profile, change a profile, change EAP or customer user data outside of a direct profile change, how the system profile edit dialog for a profile (there are a few other things that could be retrieved here as well)
Properties: Collection of wireless profiles as WlanNativeProfile objects, Collection of available wireless networks as WlanNativeNetwork objects, Interface Guid, Description, Autoconfiguration setting, background scan enabled, collection of physical radio state objects (not shown in this summary), collection of basic service sets objects (not shown in this summary), Interface state, currently used profile, current authentication algorithm, current cipher algorithm, Collection of supported authentication algorithms associated with their supported cipher algorithms as objects (not shown in this summary - one for infrastructureor adhoc), channel number, OneX enabled or disabled, Security enabled or disabled, Media streaming mode enabled or disabled, operation mode, safe mode support, certified for safe mode, and received signal strength (there are a few other things that could be retrieved here as well)
WlanNativeProfile - Class that encapsulates a specific wireless profile
Methods: All of the editing/deleting methods available for WlanNativeInterface that apply to the profile
Properties: Profile Name, UserProfile, GroupPolicyProfile
WlanNativeNetwork - Class that represents a specific wireless network
Properties: Connectable, Collection of Basic Service Set IDs, Name, SSID, BSS Type, Why it's not connectable if it's not, Signal strength, default authentication algorithm, default cipher algorithm, Collection of physical types, Security enabled
Here are a few concepts worth remembering that I've seen come up multiple times:
- Be sure to set profiles, EAP data, etc. with the all users flag set if you want the change to show up for other users. If you're not running in the same context as the user, e.g. a different session or user with code executing as a service, you need to do this in order for the changes to be used by the user.
- EAP and custom user data can be set in a profile directly. This is often more efficient than keeping up with them separately.
- Scanning for networks returns immediately and isn't additive most of the time; wait for the change event to indicate scanning is finished if you need all the networks
- Verify that profile settings are compatible with the interface by looking at the authorization types and their associated cipher algorithms by querying the interface
- Functions that take a parameter for the contents of a temporary profile want a string containing XML not a filename whose contents contains XML
- Use WlanFreeMemory properly to prevent memory leaks
- Use WlanUIEditProfile to let an end user edit a profile with the standard Windows dialog
Here are a couple screenshots of the example program:
Comments
Anonymous
February 19, 2015
Hello, I am very new to .net and have basic knowledge of programming using java. I am learning c# now. I have been using Toshiba's FlashAir wireless LAN card and have been trying to upload stuffs into it. I have been successful to do so but wanted to learn more about how I can actually create a windows app that will look for a wireless network for devices like FlashAir and get its contents, be able to upload documents and also share internet capability to other wifi enabled devices which otherwise would get no internet access. All these functionality already exist in the card just needs some additional changes in the config file. The reason for this comment is that I am trying to know if there are API that actually support these kind of ideas. The application would look for a network, connect to it and display options that can download, upload, delete, share, print contents of such devices. Thank you!Anonymous
February 22, 2015
Hi Sabin, The example code supplied has most everything that you've asked about. The two areas that it doesn't specifically cover are sharing network connections and printing content. The most straightforward way to print is going to depend on what framework you are using in the application. While using the Native API is an option, Windows Forms, WPF, and Store Apps all have their own ways of doing printing. Sharing your WiFi connections to other devices is covered at msdn.microsoft.com/.../dd815252%28v=vs.85%29.aspx. Many of those APIs are already present in the example code, but there are a few which are not. I hope that helps! In the future, this type of question would be better posed in our forums at social.msdn.microsoft.com/.../home.Anonymous
June 19, 2015
Chris, Thank you so much for posting this code. I got it to compile under VS Express 2012 by moving the WlanNative DLL to the debug directory, adding a reference to the WlanNative.dll and removing the VC++ WlanNative section from the project (I will try to figure the dual compile out later.) The program worked like a charm. Got to see all of the settings for my USB WLAN dongle and see all of the networks in the neighborhood. Really cool! I have been setting up ad hoc networks lately in Win 8.1 (yes it can be done) for speed testing of various WLAN dongles. What I would really like to do is build my own C# program for throwing data from one computer to another in ad hoc mode. Could you point to any documentation for that? Also any info covering media streaming mode would be terrific. Thanks again! BillAnonymous
June 21, 2015
Hi Bill, I've happy to hear that this was helpful for you! Starting with Windows 8.1, ad hoc is being obsoleted by WiFiDirect. There are some probable enhancements with how to interact with WiFiDirect starting in Windows 10 (see msdn.microsoft.com/.../windows.devices.wifidirect.wifidirectlegacysettings.aspx) that I'll likely blog about some time after it is released as well. If you go to Windows 10, it looks like that will be much more straightforward to use from C#. Documentation for WIFiDirect for Windows 8.1 can be found here: msdn.microsoft.com/.../dn457944(v=vs.85).aspx. For Ad-Hoc networking (prior to Windows 8.1), you'd probably want to start with the IDot11AdHocManager interface which will be the starting point for interacting with the OS for this purpose whose documentation is located here: msdn.microsoft.com/.../ms706088(v=vs.85).aspx. You'd want to use CoCreateInstance to get an instance of the interface, and from there, you can use its methods to do pretty much every ad hoc wifi.Anonymous
June 23, 2015
Hi Chris, Yes I saw the planned obsolescence of ad hoc. But I have not been able to find any working examples of C# WiFi Direct especially for desktop-Winform type programs. Because there are no code examples on the pages above, I assumed that WiFi Direct was more a good idea than an implemented interface in 8.1. (If you do plan on posting WiFi Direct working code in the near future, I would love to see it!) I do plan on upgrading to Windows 10, especially if there will be WiFi Direct support for 802.11ac and 802.11ad. BillAnonymous
June 25, 2015
Hi Chris, I am trying to create a screen within my app that allows users to view all wifi networks, connect to a network and create a profile for that network to automatically reconnect to it. In your app, there is no way to connect to a new network (Available Networks tab). Instead, you must either have an existing profile by connecting to it via windows control panel, or you must enter the xml for a temporary profile and then connect. How do I simply connect to an available network using a password? If the only way is to enter the xml, how do I get the data to create the xml? Thanks, NateAnonymous
June 25, 2015
Hi Nate, The best route to go for connecting to an available network with a password, when you don't want the user to have to do any interaction with the WLAN AutoConfig system, is to make a profile, either persistent or temporary, put the password in with it, and use it to connect. You can get the information needed to create the XML from the WlanNetwork class in the example or the WLAN_AVAILABLE_NETWORK structure against the native Windows API. There's no public function to auto-generate the XML for you from the network information unfortunately.Anonymous
June 25, 2015
Hello Chris, Thanks for your speedy reply. I have a few more questions. Here is the profile xml that I get after connecting to my wifi network in windows: <?xml version="1.0"?> <WLANProfile xmlns="www.microsoft.com/.../v1"> <name> <!--network name here--> </name> <SSIDConfig> <SSID> <hex> <!--number here--> </hex> <name> <!--network name here--> </name> </SSID> </SSIDConfig> <connectionType>ESS</connectionType> <connectionMode>manual</connectionMode> <MSM> <security> <authEncryption> <authentication>WPA2PSK</authentication> <encryption>AES</encryption> <useOneX>false</useOneX> </authEncryption> <sharedKey> <keyType>passPhrase</keyType> <protected>true</protected> <keyMaterial> <!--very long key here--> </keyMaterial> </sharedKey> </security> </MSM> </WLANProfile> Many of the items needed for my xml profile are not available via the WlanNetwork. Where would I get the following?: SSID hex connectionType connectionMode encryption keyType protected keyMaterial Also, the authentication tag is WPA2PSK, which is not an option in the WlanNetwork class nor the WLAN_AVAILABLE_NETWORK stuct it encapsulates (see _DOT11_AUTH_ALGORITHM enum in wlantypes.h. Is there a newer wlan api than the WlanNative one? Also how do I "put the password in with it"? I'm guessing that the keyMaterial tag is generated using the password, but not sure how to create that either. Thanks for your help! NateAnonymous
June 25, 2015
Hi Nate, SSIDHex is simply the hexadecimal representation of the SSID. Since the SSID is returned as a character array, not all of the characters would be visible nor legal for XML, so formatting each character as hexadecimal solves those issues. If you want to set the profile security information, you can use a plaintext key and protected set to false. Before it is saved to disk, WlanSetProfile will encrypt it and change protected to true. If you want to get the plaintext key, you can use the WLAN_PROFILE_GET_PLAINTEXT_KEY flag as described in the documentation for WlanGetProfile. The value for connectionType is determined by the type of network. If it’s Infrastructure, use ESS. If it’s adhoc, use IBSS. The value for connectionMode won’t matter for a temporary profile. If you’re saving the profile, it indicates whether or not the wireless service should automatically connect to it when it is found as an available network. The value for keyType will depend on the type of authentication as outlined here: msdn.microsoft.com/.../ms706987(v=vs.85).aspx. The authentication type can be derived from the default algorithm from the WLAN_AVAILABLE_NETWORK structure. See the documentation on the enum type for more information. In general, WPA2 is going to be one of the RSNA options depending on whether or not you’re using a PSK. See the documentation on the schema elements for wireless profiles for more information on any of the elements: msdn.microsoft.com/.../ms706965(v=vs.85).aspx.Anonymous
July 07, 2015
Hi Chris, I am able to create a temporary profile and connect with it, thanks to your help. However, I can't figure out how to configure the profile to not be temporary i.e. so that it will reconnect automatically when it sees that network again. I have tried setting the connectionMode element in the profile xml to auto, but when I unplug my wifi adapter and plug it back in it doesn't reconnect automatically. I have to instead find the network and reenter my password. NateAnonymous
July 07, 2015
Hi Nate, You can use the WlanSetProfile function to store a profile. If you have the connectionMode element set to auto in a user or gorup policy stored profile then it should auto-connect when the network becomes available again.Anonymous
January 11, 2016
Do you know how we can send and receive data over WiFi without going through IP? i.e. only using up to layer 2. If so any C# code out there please? Thank you!