首先,获取所有可用的wifi:
windows API提供WlanEnumInterfaces接口获取所有可用的wlan,详细的可以参看msdn下的例子程序,https://msdn.microsoft.com/en-us/library/windows/desktop/ms706749(v=vs.85).aspx
if (pBssEntry->bSecurityEnabled)
wprintf(L"Yes\n");
else
wprintf(L"No\n");
这里表示当前wlan连接是否需要密码。
pBssEntry =(WLAN_AVAILABLE_NETWORK *)&pBssList->Network[j];
if (pBssEntry->dot11Ssid.uSSIDLength == 0)
wifi.mName.Append(Empty);
else
{
for (k = 0; k < pBssEntry->dot11Ssid.uSSIDLength; k++)
{
//wprintf(L"%c", (int) pBssEntry->dot11Ssid.ucSSID[k]);
wsprintf(&buf[k],L"%c", (int) pBssEntry->dot11Ssid.ucSSID[k]);
}
wifi.mName.Append(buf);
}
这里可以获取wlan的名称。
if (pBssEntry->wlanSignalQuality == 0)
iRSSI = -100;
else if (pBssEntry->wlanSignalQuality == 100)
iRSSI = -50;
else
iRSSI = -100 + (pBssEntry->wlanSignalQuality/2);
这里获取wlan的信号强度。
连接之前先注册通告消息:
DWORD err = WlanRegisterNotification(
hClient,
WLAN_NOTIFICATION_SOURCE_ACM,//WLAN_NOTIFICATION_SOURCE_ALL, notifications
FALSE,
ConnectNotifyCallback,
this, // context data
NULL,
NULL
);
可以注册所有类型的通告消息,但是一般没有这个必要,注册自己想要的,这里注册的消息类型是WLAN_NOTIFICATION_SOURCE_ACM,ConnectNotifyCallback是回调函数,可以用来处理发送回来的消息。this为上下文参数,为一个对象,也就是消息由哪个对象处理。倒数第二个参数为保留参数,设为NULL;倒数第一个参数为前一个注册消息源,这里也为NULL。注册成功返回ERROR_SUCCESS。
一切完毕之后需要取消注册通告消息:
DWORD err = WlanRegisterNotification(
hClient,
WLAN_NOTIFICATION_SOURCE_NONE, // register all notifications
FALSE,
NULL,
NULL, // context data
NULL,
NULL
);
连接指定wlan:
void CWifiDialog::ConnectWlan()
{
int index;
int err;
CString key;
GUID pInterfaceGuid = pIfInfo->InterfaceGuid;
TCHAR profile[2048] = {0};
index = mWifiList->GetCurSel();
pBssEntry =(WLAN_AVAILABLE_NETWORK *)&pBssList->Network[index];
WLAN_CONNECTION_PARAMETERS ConnPara;
if (need a key)
{
//这里可以由用户输入密码
key = GetKey();
wsprintf(profile, WPProfileKey, wifi.mName, wifi.mName, key);
}
else
{
//不需要密码
wsprintf(profile, WPProfileNoKey, wifi.mName, wifi.mName);
}
ConnPara.pDot11Ssid = &(pBssEntry->dot11Ssid);//pDot11Ssid; // SSID
ConnPara.dot11BssType = pBssEntry->dot11BssType; // BSS type
ConnPara.pDesiredBssidList = NULL; // no desired BSSID
ConnPara.strProfile = profile;//NULL; // no profile
ConnPara.wlanConnectionMode = wlan_connection_mode_temporary_profile;//wlan_connection_mode_discovery_secure;
ConnPara.dwFlags = 0; // no connection flag
err = WlanConnect(hClient, &pInterfaceGuid, &ConnPara, NULL);
//WLAN_CONNECTION_ADHOC_JOIN_ONLY
if (err == ERROR_SUCCESS)
{
//TODO:如保存密码
}
else if (err == ERROR_INVALID_PARAMETER)
{
}
else if (err == ERROR_INVALID_HANDLE)
{
}
else if (err == ERROR_ACCESS_DENIED)
{
}
else
{
if (mWifis.at(index).mIsLocked)
{
ConnectWlan();
}
else
{
return;
}
}
}
如果连接没有成功,重连。
连接状态监听:
void OnConnect(PWLAN_NOTIFICATION_DATA data)
{
int err;
CString hint;
hint.Append(_T("连接"));
hint.Append(mWifis.at(mCurIndex).mName);
if (data->InterfaceGuid == pIfInfo->InterfaceGuid)
{
if (data->NotificationSource == WLAN_NOTIFICATION_SOURCE_ACM)
{
if (data->NotificationCode == wlan_notification_acm_connection_start)
{
hint.Append(_T("开始"));
}
else if(data->NotificationCode == wlan_notification_acm_connection_complete)
{
hint.Append(_T("成功"));
}
else if (data->NotificationCode == wlan_notification_acm_connection_attempt_fail)
{
hint.Append(_T("失败"));
}
else if (data->NotificationCode == wlan_notification_acm_disconnected)
{
}
}
}
}
if (data->InterfaceGuid == pIfInfo->InterfaceGuid)判断过滤通告消息。
NotificationSource == WLAN_NOTIFICATION_SOURCE_ACM 通知源是WLAN_NOTIFICATION_SOURCE_ACM ,其他源的不处理,接着处理通知码,wlan_notification_acm_disconnected表示断开一个连接,例如,连接另外一个wlan时,就需要断开当前连接(如果当前已经有连接),wlan_notification_acm_connection_start表示连接开始,wlan_notification_acm_connection_complete表示连接成功。
WLANProfile设置:
当进行wlan连接时,ConnPara.wlanConnectionMode 设置为 wlan_connection_mode_temporary_profile时需要设置WLANProfile,WLANProfile例子如下:
_T("<?xml version=\"1.0\" encoding=\"US-ASCII\"?>\
<WLANProfile xmlns=\"http://www.microsoft.com/networking/WLAN/profile/v1\">\
<name>%s</name>\
<SSIDConfig>\
<SSID>\
<name>%s</name>\
</SSID>\
</SSIDConfig>\
<connectionType>ESS</connectionType>\
<connectionMode>auto</connectionMode>\
<autoSwitch>false</autoSwitch>\
<MSM>\
<security>\
<authEncryption>\
<authentication>WPA2PSK</authentication>\
<encryption>AES</encryption>\
<useOneX>false</useOneX>\
</authEncryption>\
<sharedKey>\
<keyType>passPhrase</keyType>\
<protected>false</protected>\
<keyMaterial>%s</keyMaterial>\
</sharedKey>\
</security>\
</MSM>\
</WLANProfile>")
keyMaterial 出设置wlan密码,name处为wlan 的SSID。
可以使用命令: netsh wlan export profile %SSIDName% folder=D:\ 导出指定SSID的 wlan profile。不过导出的profile中keyMaterial 一般已经过加密处理。