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 );</div>
由可用列表便可以找到当前哪个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");}
</div>
3.断开连接
如果wifi处于连接状态,将其断开。WlanDisconnect还是容易使用的。原型如下:
DWORD WINAPI WlanDisconnect( _In_ HANDLE hClientHandle, _In_ const GUID *pInterfaceGuid, _Reserved_ PVOID pReserved );</div>
代码演示在后面。
4.连接一个有profile的AP(已保存过密码)
这是本文的重点。
虽然连接函数WlanConnect原型很简单:
DWORD WINAPI WlanConnect( _In_ HANDLE hClientHandle, _In_ const GUID *pInterfaceGuid, _In_ const PWLAN_CONNECTION_PARAMETERS pConnectionParameters, _Reserved_ PVOID pReserved );</div> 还好我的需求还是蛮简单的,只要连接已有的profile的AP。那么我的工作就会有针对性的开展。挫折了好多天,每次都连接失败,原因是ERROR_INVALID_PARAMETER。
就在今天,我终于成功了。真是会者不难,难者不会啊。
看看连接参数的结构体:
</div>
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;
</div>
为了实现我的要求,可以这样赋值:
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 card
PWLAN_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"W

