有心栽花花不开,无心插柳柳成排。
今天要说的这个wifi on\off是在软件层面控制无线网卡的开和关。
问题听起来简单,调查起来复杂,但解决起来却也简单。关键函数便是Native wifi api中的WlanSetInterface。其实这个API功能也是非
常强大的,我只用到其中控制wifi radio state的功能。官网文档在此。
函数原型:
DWORD WINAPI WlanSetInterface(
_In_ HANDLE hClientHandle,
_In_ const GUID *pInterfaceGuid,
_In_ WLAN_INTF_OPCODE OpCode,
_In_ DWORD dwDataSize,
_In_ const PVOID pData,
_Reserved_ PVOID pReserved
);
重点说一下三个参数:
1. OpCode,指定要设置的参数。我们选择wlan_intf_opcode_radio_state
2. DwDataSize,pData的size。传入时用sizeof得到。
3. pData,radio state对应的data是WLAN_PHY_RADIO_STATE。
看看这个state结构体:
typedef struct _WLAN_PHY_RADIO_STATE {
DWORD dwPhyIndex;
DOT11_RADIO_STATE dot11SoftwareRadioState;
DOT11_RADIO_STATE dot11HardwareRadioState;
} WLAN_PHY_RADIO_STATE, *PWLAN_PHY_RADIO_STATE;
Index设为0.
State设置如下:
typedef enum _DOT11_RADIO_STATE {
dot11_radio_state_unknown,
dot11_radio_state_on,
dot11_radio_state_off
} DOT11_RADIO_STATE, *PDOT11_RADIO_STATE;
与前几个API(比如wlanconnect)相比,这个函数的使用简单多了。全部源码如下:
// ManageWirelessNetwork.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <stdio.h>
#include <windows.h>
#include <shellapi.h>
#include <wlanapi.h>
// Need to link with shell32.lib
#pragma comment(lib, "shell32.lib")
#pragma comment(lib, "wlanapi.lib")
int _tmain(int argc, _TCHAR* argv[])
{
DWORD dwResult = 0;
DWORD dwMaxClient = 2;
DWORD dwCurVersion = 0;
HANDLE hClient = NULL;
PWLAN_INTERFACE_INFO_LIST pIfList = NULL;
PWLAN_INTERFACE_INFO pIfInfo = NULL;
dwResult = WlanOpenHandle(dwMaxClient, NULL, &dwCurVersion, &hClient);
if (dwResult != ERROR_SUCCESS) {
wprintf(L"WlanOpenHandle failed with error: %u\n", dwResult);
return false;
}
dwResult = WlanEnumInterfaces(hClient, NULL, &pIfList);
if (dwResult != ERROR_SUCCESS) {
wprintf(L"WlanEnumInterfaces failed with error: %u\n", dwResult);
return false;
}
WLAN_PHY_RADIO_STATE state;
state.dwPhyIndex = 0;
state.dot11SoftwareRadioState = dot11_radio_state_on;
PVOID pData = &state;
dwResult = WlanSetInterface(hClient,&pIfList->InterfaceInfo[0].InterfaceGuid,
wlan_intf_opcode_radio_state,sizeof(WLAN_PHY_RADIO_STATE),pData,NULL);
if(dwResult == ERROR_SUCCESS)
{
wprintf(L"set state success!\n");
}
else
{
wprintf(L"set state failed!err is %d\n",dwResult);
}
return 0;
}
后记:
其实几个月前就要实现windows上的wifi on和off,问了许多人,发了许多帖子,最后都不了了之。之后的日子里也发生了许多事。国内的
搜索无果,加上google的无法使用,都对调查增加了些许难度。我们把重点先放到了native wifi api的几个方法,见上一篇玩转文章。但
那并不是我想要的。
原以为windows也会想android一样,普通应用没有权限来控制wifi的开关呢,结果并不是这样。这也宣告了之前我的判断失误。
直到今天,通过Bing发现了几条线索。那是通过C#调用native wifi api的问题,里面提及了之前并没有重视的wlansetinterface。
Interface,在这里我觉得可以理解成无线网卡。类似的WlanEnumInterfaces中实现的功能是罗列出当前无线网卡。
无线网卡的设置,其中有一项是radio的状态。
果然,这一切都有了了断。