天天看点

windows下自动切换并连接wifi热点

这段时间做的一个项目,需要测试产品上wifi模块的功能。测试方式:该wifi模块作为AP热点,笔记本连接这个热点,然后ping外网,ping得通就表示功能OK。废话不多说,进入正题。

windows初次连接某个wifi热点的过程中,有一个很关键的步骤:生成wifi配置文件(下面简称profile),当然,这一步是windows根据你的wifi热点自动生成的,所以想要让电脑自动连接一个未连接过的热点,软件必须拼接出一个profile文件,并添加到windows的wifi列表中。profile一般格式如下图:

windows下自动切换并连接wifi热点

不同的wifi热点profile不太一样,上图是我的测试产品热点的profile,毕竟是量产产品,数量比较大,设置为不加密是为了方便修改它,只需要修改热点名就可以。

profile文件已经有了,需要用netsh工具添加到windows的wifi列表里面去,比如我的profile存放在D盘,用下面的命令:

netsh wlan add profile filename="D:\\\wifitest.xml"  #这里用绝对路径,文件名跟文件里的name要一样
           

设置参数:配置文件名,热点名以及密码

netsh wlan set profileparameter name=wifitest SSIDname="test_ap" keyMaterial=12345678
           

连接wifi热点:

netsh wlan connect name=wifitest ssid="test_ap"
           

ping外网:

ping  www.baidu.com
           

手动操作到这里就结束了,但身为一介码农,自动化测试才是你的价值体现。

VC++下自动连接wifi热点

根据上面的描述,总结几个关键的步骤:

  1. 根据已有的配置文件,修改wifi热点名(有必要的话密码也修改,我们的测试产品密码用的都是同样的);
  2. 将配置文件添加到windows的wifi列表;
  3. 设置配置文件参数;
  4. 连接热点;
  5. ping外网

思路:wifi的ssid作为输入,修改xml文件中的热点名,把上面用到的netsh命令写成bat脚本,然后在程序里修改bat脚本并执行,代码实现如下:(string和wstring相互转换的接口是从网上找的)

// An highlighted block
#include "tinyxml.h"
#include <wlanapi.h>
#include <windows.h>
#include <iostream>
#include <fstream>

//wstring to string
std::string ConvertWStringToAnsi(std::wstring wstr)
{
	std::string result;
	int len = WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), wstr.size(), NULL, 0, NULL, NULL);
	if( len <= 0 )
		return result;
 
	char* buffer = new char[len + 1];
	if(buffer == NULL )
		return result;
 
	WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), wstr.size(), buffer, len, NULL, NULL);
	buffer[len] = '\0';
	result.append(buffer);
	delete[] buffer;
 
	return result;
}

//string to wstring
std::wstring ConvertAnsiToWString(std::string str)
{
	std::wstring result;
 
	int len = MultiByteToWideChar(CP_ACP, 0, str.c_str(), str.size(), NULL, 0);
	if( len < 0 )
		return result;
 
	wchar_t* buffer = new wchar_t[len + 1];
	if( buffer == NULL )
		return result;
 
	MultiByteToWideChar(CP_ACP, 0, str.c_str(), str.size(), buffer, len);
 
	buffer[len] = '\0';
	result.append(buffer);
	delete[] buffer;
 
	return result;
}

bool Modify_BatFile(std::wstring path, std::string ssid)
{
	ifstream ifile;
	
	std::string PathTmp = ConvertWStringToAnsi(path);
	ifile.open(PathTmp.c_str(), ios::in);
	if(!ifile.is_open())
	{
		return false;
	}

	std::string bakfile = PathTmp + ".bak";
	ofstream ofile(bakfile.c_str());
	if(!ofile)
	{
		return false;
	}
	
	char strline[1024] = {0};
	while(ifile.good() && !ifile.eof())
	{
		memset(strline, 0x00, sizeof(strline));
		ifile.getline(strline, 1024);
		
		if(strstr(strline, "set SSID="))
		{
			ofile << "set SSID=" << ssid << std::endl;
			continue;
		}
		ofile << strline << std::endl;
	}

	ifile.close();
	ofile.close();
	
	if(!DeleteFile(path.c_str()))
	{
		return false;
	}
	if(rename(bakfile.c_str(), PathTmp.c_str()))
	{
		return false;
	}

	return true;
}
//修改bat脚本接口
bool Modify_Wifi_Profile(std::string ssid)
{
	TiXmlDocument doc;
	
	std::string filename = "D:\\wifitest.xml";
	if(!doc.LoadFile(filename.c_str()))
	{
		return false;
	}

	TiXmlElement *Root = doc.RootElement();
	TiXmlNode *SSIDConfig = Root->FirstChild("SSIDConfig");
	if(!SSIDConfig)//can't find SSIDConfig
	{
		return false;
	}
	
	TiXmlNode *SSID = SSIDConfig->FirstChild("SSID");//因为我们需要的ssid热点名:name是SSID的子节点,所以先找父节点
	if(!SSID)//can't find SSID
	{
		return false;
	}

	TiXmlNode *name = SSID->FirstChild("name");//找到ssid热点名,修改为传入的ssid
	if(!name)
	{
		return false;
	}
	TiXmlText nameText(ssid.c_str());
	TiXmlNode *name_tmp = name->FirstChild();
	name->ReplaceChild(name_tmp, nameText);

	doc.SaveFile("D:\\wifitest.xml");

	std::wstring pingPath = L"D:\\test.bat";
	if(false == Modify_BatFile(pingPath, ssid))
	{
		return false;
	}
	
	int ret = ShellExecute(NULL, L"open", pingPath.c_str(), NULL, NULL, SW_SHOWNORMAL);
	if(ret < 32)//if shellexcute failed, the return value would be < 32,.Why? please Baidu.
	{
		return false;
	}

	return true;
}
           

bat脚本,里面有部分参考了Roger0212大神的代码,原文链接:https://blog.csdn.net/lile777/article/details/78686727

@echo off
title wifi测试
echo.
echo.

set SSID=test_ap
netsh wlan delete profile name="wifitest"	::因为我在测试过程中用的同一个profile,所以在下次测试之前需要先把原来的删掉,再重新添加
netsh wlan add profile filename="D:\\wifitest.xml"
netsh wlan set profileparameter name=wifitest SSIDname="%SSID%" keyMaterial=12345678
netsh wlan connect name=wifitest ssid="%SSID%"

::下面这部分参考了大神:Roger0212的代码,原文链接https://blog.csdn.net/lile777/article/details/78686727 
ping -n 2 www.baidu.com > %temp%\1.ping    
findstr "TTL" %temp%\1.ping > nul
if %errorlevel%==0 (echo     √ 外网正常) else (echo     × 外网不通)         
if exist %temp%\*.ping del %temp%\*.ping

echo.
echo.
pause
           

上面就是本次的分享了,有什么不合理的请及时指正,谢谢。