Windows应用想要实现连接wifi,监听wifi信号,断开连接等功能,用NativeWifi API是个不错的选择。

打开MSDN,搜索NativeWifi Api,找到Native Wifi页。在这里。

信息量很大,如果像我着急实现上述功能,看海量的文档有些来不及。如果直接给我例子,在运行中调试,阅读代码,效率会更高。

但是,我并没有成功。首先,Sample在SDK

中,参见这里。我下载几次都失败了,最后放弃这条路。后来同事给了我一份Sample,我不敢确定是否就是这个,但是代码写的也是很晦涩。我的初衷是简单的使用这些API的例子。

看来还是自己动手吧。看相关API,如果不懂,就找有经验人的例子。

几经周折,终于实现我的需求。让我慢慢道来。

1.获得可用AP列表

参见WlanGetAvailableNetworkList的官方文档,下面有例子。

DWORD WINAPI WlanGetAvailableNetworkList(_In_        HANDLE hClientHandle,_In_        const GUID *pInterfaceGuid,_In_        DWORD dwFlags,_Reserved_  PVOID pReserved,_Out_       PWLAN_AVAILABLE_NETWORK_LIST *ppAvailableNetworkList
);

由可用列表便可以找到当前哪个AP正在连接,并显示信号强度。

2.监听当前连接

在获得可用AP列表的基础上,遍历当前AP,看谁正在连接,并取得它的信号。代码片段如下:

bool isConnect = false;
int numberOfItems = pWLAN_AVAILABLE_NETWORK_LIST->dwNumberOfItems;for(int i = 0; i <= numberOfItems; i++){WLAN_AVAILABLE_NETWORK wlanAN = pWLAN_AVAILABLE_NETWORK_LIST->Network[i];if(wlanAN.dwFlags & WLAN_AVAILABLE_NETWORK_CONNECTED){Wprintf(WLAN signal is %s:%d\n",  wlanAN.strProfileName, wlanAN.wlanSignalQuality);isConnect = true;              }}if(!isConnect){            wprintf("Wifi is disconnected!\n");}

3.断开连接

如果wifi处于连接状态,将其断开。WlanDisconnect还是容易使用的。原型如下:

DWORD WINAPI WlanDisconnect(_In_        HANDLE hClientHandle,_In_        const GUID *pInterfaceGuid,_Reserved_  PVOID pReserved
);

代码演示在后面。

4.连接一个有profile的AP(已保存过密码)

这是本文的重点。
虽然连接函数WlanConnect原型很简单:

DWORD WINAPI WlanConnect(_In_        HANDLE hClientHandle,_In_        const GUID *pInterfaceGuid,_In_        const PWLAN_CONNECTION_PARAMETERS pConnectionParameters,_Reserved_  PVOID pReserved
);

但参数PWLAN_CONNECTION_PARAMETERS却是很复杂,只要有一个配错,连接就会失败。
还好我的需求还是蛮简单的,只要连接已有的profile的AP。那么我的工作就会有针对性的开展。挫折了好多天,每次都连接失败,原因是ERROR_INVALID_PARAMETER。
就在今天,我终于成功了。真是会者不难,难者不会啊。
看看连接参数的结构体:

typedef struct _WLAN_CONNECTION_PARAMETERS {WLAN_CONNECTION_MODE wlanConnectionMode;LPCWSTR              strProfile;PDOT11_SSID          pDot11Ssid;PDOT11_BSSID_LIST    pDesiredBssidList;DOT11_BSS_TYPE       dot11BssType;DWORD                dwFlags;
} WLAN_CONNECTION_PARAMETERS, *PWLAN_CONNECTION_PARAMETERS;

为了实现我的要求,可以这样赋值:
wlanConnectionMode这里设成wlan_connection_mode_profile
strProfile写上你要连接ap的名称(通常是profile名称)
pDot11Ssid用不上,设置NULL
pDesiredBssidList同样置成NULL
dot11BssType我给设成dot11_BSS_type_infrastructure(基础设施?)
dwFlags设置为WLAN_CONNECTION_HIDDEN_NETWORK
确实是工作了,strProfile如何获取呢?参见监听连接信号中对可用AP列表中第一个profile的获取。
完整代码如下:

//
#include "stdafx.h"
#include <windows.h>
#include <wlanapi.h>
#include <objbase.h>
#include <wtypes.h>
#include <string>
#include <stdio.h>
#include <stdlib.h>// Need to link with Wlanapi.lib and Ole32.lib
#pragma comment(lib, "wlanapi.lib")
#pragma comment(lib, "ole32.lib")using namespace std;int listenStatus()
{HANDLE hClient = NULL;DWORD dwMaxClient = 2;       DWORD dwCurVersion = 0;DWORD dwResult = 0;DWORD dwRetVal = 0;int iRet = 0;WCHAR GuidString[39] = {0};//Listen the status of the AP you connected.while(1){Sleep(5000);PWLAN_INTERFACE_INFO_LIST pIfList = NULL;//I think wlan interface means network cardPWLAN_INTERFACE_INFO pIfInfo = NULL;DWORD dwFlags = 0;       dwResult = WlanOpenHandle(dwMaxClient, NULL, &dwCurVersion, &hClient);if (dwResult != ERROR_SUCCESS) {wprintf(L"WlanOpenHandle failed with error: %u\n", dwResult);return 1;}dwResult = WlanEnumInterfaces(hClient, NULL, &pIfList);if (dwResult != ERROR_SUCCESS) {wprintf(L"WlanEnumInterfaces failed with error: %u\n", dwResult);return 1;} else {wprintf(L"WLAN_INTERFACE_INFO_LIST for this system\n");wprintf(L"Num Entries: %lu\n", pIfList->dwNumberOfItems);wprintf(L"Current Index: %lu\n\n", pIfList->dwIndex);int i;for (i = 0; i < (int) pIfList->dwNumberOfItems; i++) {pIfInfo = (WLAN_INTERFACE_INFO *) &pIfList->InterfaceInfo[i];wprintf(L"  Interface Index[%u]:\t %lu\n", i, i);iRet = StringFromGUID2(pIfInfo->InterfaceGuid, (LPOLESTR) &GuidString, sizeof(GuidString)/sizeof(*GuidString)); if (iRet == 0)wprintf(L"StringFromGUID2 failed\n");else {wprintf(L"  InterfaceGUID[%d]: %ws\n",i, GuidString);}    wprintf(L"  Interface Description[%d]: %ws", i, pIfInfo->strInterfaceDescription);wprintf(L"\n");wprintf(L"  Interface State[%d]:\t ", i);switch (pIfInfo->isState) {case wlan_interface_state_not_ready:wprintf(L"Not ready\n");break;case wlan_interface_state_connected:wprintf(L"Connected\n");break;case wlan_interface_state_ad_hoc_network_formed:wprintf(L"First node in a ad hoc network\n");break;case wlan_interface_state_disconnecting:wprintf(L"Disconnecting\n");break;case wlan_interface_state_disconnected:wprintf(L"Not connected\n");break;case wlan_interface_state_associating:wprintf(L"Attempting to associate with a network\n");break;case wlan_interface_state_discovering:wprintf(L"Auto configuration is discovering settings for the network\n");break;case wlan_interface_state_authenticating:wprintf(L"In process of authenticating\n");break;default:wprintf(L"Unknown state %ld\n", pIfInfo->isState);break;}}}}
}int _tmain(int argc, _TCHAR* argv[])
{HANDLE hClient = NULL;DWORD dwMaxClient = 2;       DWORD dwCurVersion = 0;DWORD dwResult = 0;DWORD dwRetVal = 0;int iRet = 0;    /* variables used for WlanEnumInterfaces  */PWLAN_INTERFACE_INFO_LIST pIfList = NULL;PWLAN_INTERFACE_INFO pIfInfo = NULL;LPCWSTR pProfileName = NULL;LPWSTR pProfileXml = NULL;DWORD dwFlags = 0;pProfileName = argv[1];wprintf(L"Information for profile: %ws\n\n", pProfileName);dwResult = WlanOpenHandle(dwMaxClient, NULL, &dwCurVersion, &hClient);if (dwResult != ERROR_SUCCESS) {wprintf(L"WlanOpenHandle failed with error: %u\n", dwResult);return 1;}dwResult = WlanEnumInterfaces(hClient, NULL, &pIfList);if (dwResult != ERROR_SUCCESS) {wprintf(L"WlanEnumInterfaces failed with error: %u\n", dwResult);return 1;} else {dwResult = WlanDisconnect(hClient, &pIfList->InterfaceInfo[0].InterfaceGuid,NULL);//DISCONNECT FIRSTif(dwResult != ERROR_SUCCESS){printf("WlanDisconnect failed with error: %u\n",dwResult);return -1;}PWLAN_AVAILABLE_NETWORK_LIST pWLAN_AVAILABLE_NETWORK_LIST = NULL;dwResult = WlanGetAvailableNetworkList(hClient, &pIfList->InterfaceInfo[0].InterfaceGuid,WLAN_AVAILABLE_NETWORK_INCLUDE_ALL_MANUAL_HIDDEN_PROFILES,NULL, &pWLAN_AVAILABLE_NETWORK_LIST);if (dwResult != ERROR_SUCCESS){            printf("WlanGetAvailableNetworkList failed with error: %u\n",dwResult);WlanFreeMemory(pWLAN_AVAILABLE_NETWORK_LIST);return -1;}WLAN_AVAILABLE_NETWORK wlanAN = pWLAN_AVAILABLE_NETWORK_LIST->Network[0];//PLEASE CHECK THIS YOURSELFif(pProfileName == NULL)pProfileName = wlanAN.strProfileName;   WLAN_CONNECTION_PARAMETERS wlanConnPara;wlanConnPara.wlanConnectionMode =wlan_connection_mode_profile ; //YES,WE CONNECT AP VIA THE PROFILEwlanConnPara.strProfile =pProfileName;                           // set the profile namewlanConnPara.pDot11Ssid = NULL;                                 // SET SSID NULLwlanConnPara.dot11BssType = dot11_BSS_type_infrastructure;     //dot11_BSS_type_any,I do not need it this time.        wlanConnPara.pDesiredBssidList = NULL;                         // the desired BSSID list is emptywlanConnPara.dwFlags = WLAN_CONNECTION_HIDDEN_NETWORK;           //it works on my WIN7\8dwResult=WlanConnect(hClient,&pIfList->InterfaceInfo[0].InterfaceGuid,&wlanConnPara ,NULL);if (dwResult==ERROR_SUCCESS){printf("WlanConnect success!\n");}else{printf("WlanConnect failed err is %d\n",dwResult);}}listenStatus(); //LISTEN THE STATUSif (pProfileXml != NULL) {WlanFreeMemory(pProfileXml);pProfileXml = NULL;}if (pIfList != NULL) {WlanFreeMemory(pIfList);pIfList = NULL;}return dwRetVal;
}

5.打开网络设置界面

遇到以前没有连接过的AP,需要输入密码,那么,直接打开配置界面让用户自己来搞吧。

    ShellExecute(NULL, L"open", L"shell:::{21EC2020-3AEA-1069-A2DD-08002B30309D}\\::{38a98528-6cbf-4ca9-8dc0-b1e1d10f7b1b}",NULL,NULL,SW_SHOWNORMAL);

6.最后

当屏幕上打印出“WlanConnect success!”的时候,别提多高兴了。

就像爱迪生试验灯丝一下,在无数次失败后,终于找到了一种材料可以胜任灯丝的工作。这种喜悦真的令人振奋,往日的阴霾和不爽终于一扫而光。
其实我也尝试过WlanGetProfile和WlanSetProfile,虽然有时结果是能够连上指定AP,但是函数返回结果却总是ERROR_INVALID_PARAMETER。
网上的例子,很多都是抄来抄去的,写的不明不白,虽然有过帮助,但是也有些误导。
今天自己成功的连接到指定AP了(用命令行运行我的例子,输入参数profile name),我一定要把它发表出来,让其他人有个参考。
我认为这是一件诚意的作品,在此也谢谢给过我帮助的朋友。
最后说一下获得的信号。标准信号RSSI是负值,而这里获得的信号都是正值(0~100),在有些需要RSSI的地方,我们需要转换一下:

                   if (pBssEntry->wlanSignalQuality == 0)iRSSI = -100;else if (pBssEntry->wlanSignalQuality == 100)   iRSSI = -50;elseiRSSI = -100 + (pBssEntry->wlanSignalQuality/2);    wprintf(L"  Signal Quality[%u]:\t %u (RSSI: %i dBm)\n", j, pBssEntry->wlanSignalQuality, iRSSI);

本文到此完毕,虽然没有涵盖大部分API,但还是欢迎大家留意讨论。



VC++玩转Native Wifi API相关推荐

  1. Native wifi API使用

    一.WlanOpenHandle打开一个客户端句柄 [cpp] view plaincopy DWORD WINAPI WlanOpenHandle( __in DWORD dwClientVersi ...

  2. 漫谈可视化Prefuse(四)---被玩坏的Prefuse API

    这个双12,别人都在抢红包.逛淘宝.上京东,我选择再续我的"漫谈可视化"系列(好了,不装了,其实是郎中羞涩...) 上篇<漫谈可视化Prefuse(三)---Prefuse ...

  3. Java JVM、JNI、Native Function Interface、Create New Process Native Function API Analysis

    目录 1. JAVA JVM 2. Java JNI: Java Native Interface 3. Java Create New Process Native Function API Ana ...

  4. 如何使用Native Messaging API 打开window程序

    问 如何使用Native Messaging API 打开window程序 cmd javascript terminal chrome Tychio 2013年03月26日提问 关注 1 关注 收藏 ...

  5. node-webkit学习(4)Native UI API 之window

    4.1  WINDOW API概述 node-webkit版本>= v0.3.0才支持window api. Native GUI API中的window是对DOM页面的windows的一个封装 ...

  6. node-webki NATIVE UI API概览

    3.1  NATIVE UI API概览 Native UI API,是提供了在代码中访问.控制应用程序界面显示的接口.和使用node.js模块类似,想要访问node-webkit的Native UI ...

  7. Jboss EAP:native management API学习

    上一节已经学习了CLI命令行来控制JBOSS,如果想在程序中以编码方式来控制JBOSS,可以参考下面的代码,实际上在前面的文章,用代码控制Jboss上的DataSource,已经有所接触了,API与C ...

  8. React Native - Keyboard API使用详解(监听处理键盘事件)

    参考: React Native - Keyboard API使用详解(监听处理键盘事件) 当我们点击输入框时,手机的软键盘会自动弹出,以便用户进行输入. 但有时我们想在键盘弹出时对页面布局做个调整, ...

  9. C#使用Managed Wifi API连接带密码的SSID .

    Managed Wifi API的安装和使用可以参考: http://blog.csdn.net/m593192219/article/details/9363355 上面这篇文章有写了如何连接无密码 ...

最新文章

  1. pytorch优化器与学习率设置详解
  2. PyQt5教程7:布局Layout管理
  3. 嵩天-Python语言程序设计程序题--第七周:文件和数据格式化
  4. 4.3英寸屏双核 LG Prada K2通过FCC认证
  5. 数据采集组件:Flume基础用法和Kafka集成
  6. 冒泡排序法和选择排序法
  7. cad lisp 法兰6_南昌平板法兰加工设备_山东平安数控机械有限公司
  8. 运算符和结合性(转)
  9. Cisco笔记1-访问CISCO 路由器的方法
  10. 前中后序遍历的递归与非递归算法,层序遍历
  11. 微信公众号后台接口文档
  12. 对无序的边界点排序(顺时针绘制边界)
  13. Server-sent events(SSE) EventSource 客户端使用与服务器基础实现(基于Node.js)
  14. Win10设置每天定时运行某程序(关注不迷路,加星不糊涂哦~)
  15. 记一次刷票过程的感想
  16. 某云不限速破解详细教程附工具
  17. 2023年京东炸年兽脚本《京东炸年兽活动脚本》
  18. 【FastGAN】★Towards Faster and Stabilized GAN Training for High-fidelity Few-shot Image Synthesis
  19. 小技巧:systeminfo查看系统信息
  20. 没资源也能赚钱!跑跑步就能赚钱!

热门文章

  1. 快速学习Spring Boot
  2. 斐讯音箱控制扫地机器人_斐讯扫地机器人app
  3. appcan中的微信分享与qq分享
  4. 博客的WordPress地址(URL)修改后博客打不开解决方法
  5. 史鉴使人明智;诗歌使人巧慧;数学使人精细;博物使人深沉;伦理之学使人庄重;逻辑与修辞使人善辩
  6. js 相对路径转为绝对路径
  7. 计算机中数值数据编码(大计基复习资料)
  8. mysql 文本 挖掘_GitHub - cwff520/dianping_textmining: 大众点评评论文本挖掘,包括点评数据爬取、数据清洗入库、数据分析、评论情感分析等的完整挖掘项目...
  9. 求数组所有非空子序列的和
  10. 涪陵创新计算机学校2015元旦晚会,喜报:重庆市涪陵信息技术学校2019高考再续辉煌...