C++ Windows下连接WIFI

#pragma once
#include <windows.h>
#include <wlanapi.h>
#pragma comment(lib, "wlanapi.lib")

//连接方式
#define MODE_AUTO "auto"
#define MODE_MANUAL "manual"

//认证方式
#define AUTH_WPAPSK "WPAPSK"
#define AUTH_WPA2PSK "WPA2PSK"

//加密方式
#define ENCR_AES "AES"
#define ENCR_TKIP "TKIP"

/*WIFI信息*/
struct WifiInfo 
{
	char account[64];

	char password[64];

	char mode[32];

	char auth[32];

	char encrypt[32];
};

class WifiMgr
{
public:
	WifiMgr();

	~WifiMgr();

	bool connect(const char* account, const char* password, const char* mode = MODE_MANUAL,
		const char* auth = AUTH_WPAPSK, const char* encrypt = ENCR_AES);

	bool connect(const WifiInfo& info);

	bool reconnect();

	bool disconnect(bool removeProFile = true);

	bool connected() const;

	const char* getLastError() const;
protected:
	static void _stdcall wlanNotification(PWLAN_NOTIFICATION_DATA data, void* args);
private:
	bool m_connected = false;

	bool m_reconnect = false;

	char m_lastError[256] = { "未知错误" };

	HANDLE m_handle = INVALID_HANDLE_VALUE;

	PWLAN_INTERFACE_INFO_LIST m_infoList = nullptr;

	WifiInfo m_wifiInfo = { 0 };
};
#include "WifiMgr.h"
#include <stdio.h>
#include <string>

WifiMgr::WifiMgr()
{
}

WifiMgr::~WifiMgr()
{
	if (m_connected)
	{
		disconnect();
	}
}

bool WifiMgr::connect(const char* account, const char* password, const char* mode,
	const char* auth, const char* encrypt)
{
	bool result = false;
	do
	{
		if (!m_reconnect)
		{
			strcpy(m_wifiInfo.account, account);
			strcpy(m_wifiInfo.password, password);
			strcpy(m_wifiInfo.mode, mode);
			strcpy(m_wifiInfo.auth, auth);
			strcpy(m_wifiInfo.encrypt, encrypt);
		}

		unsigned long version = 0, value = 0;
		value = WlanOpenHandle(WLAN_API_VERSION, nullptr, &version, &m_handle);
		if (value != ERROR_SUCCESS)
		{
			sprintf(m_lastError, "打开WIFI句柄失败,错误代码:%lu", value);
			break;
		}

		value = WlanEnumInterfaces(m_handle, nullptr, &m_infoList);
		if (value != ERROR_SUCCESS)
		{
			disconnect();
			sprintf(m_lastError, "枚举WIFI接口失败,错误代码:%lu", value);
			break;
		}

		std::string character = std::string(password);
		for (std::string::size_type pos = 0; pos != std::string::npos; pos += strlen("&amp;"))
		{
			pos = character.find("&", pos);
			if (pos != std::string::npos)
				character.replace(pos, strlen("&"), "&amp;");
			else
				break;
		}

		char xmlBuffer[4096] = { 0 };
		sprintf(xmlBuffer, "<?xml version =\"1.0\"?>\
                             <WLANProfile xmlns =\"http://www.microsoft.com/networking/WLAN/profile/v1\">\
                             <name>%s</name>\
                             <SSIDConfig>\
                             <SSID>\
                             <name>%s</name>\
                             </SSID>\
                             </SSIDConfig>\
                             <connectionType>ESS</connectionType>\
                             <connectionMode>%s</connectionMode>\
                             <autoSwitch>false</autoSwitch>\
                             <MSM>\
                             <security>\
                             <authEncryption>\
                             <authentication>%s</authentication>\
                             <encryption>%s</encryption>\
                             <useOneX>false</useOneX>\
                             </authEncryption>\
                             <sharedKey>\
                             <keyType>passPhrase</keyType>\
                             <protected>false</protected>\
                             <keyMaterial>%s</keyMaterial>\
                             </sharedKey>\
                             </security>\
                             </MSM>\
                             </WLANProfile>",
			account, account, mode, auth, encrypt, character.c_str());

		wchar_t fileData[4096] = { 0 };
		int length = strlen(xmlBuffer);
		for (int j = 0; j < length; j++)
		{
			mbtowc(&fileData[j], &xmlBuffer[j], 1);
		}
		fileData[length] = '\0';

		WLAN_REASON_CODE reasonCode = 0;
		value = WlanSetProfile(m_handle, &m_infoList->InterfaceInfo[0].InterfaceGuid,
			0, fileData, nullptr, TRUE, nullptr, &reasonCode);
		if (value != ERROR_SUCCESS)
		{
			disconnect();
			sprintf(m_lastError, "设置WIFI配置文件失败,错误代码:%lu", value);
			break;
		}

		wchar_t wideSsid[512] = { 0 };
		if (!MultiByteToWideChar(CP_ACP, 0, account, strlen(account) + 1,
			wideSsid, sizeof(wideSsid) / sizeof(wideSsid[0])))
		{
			disconnect();
			sprintf(m_lastError, "多字符转宽字符失败,错误代码:%lu", GetLastError());
			break;
		}

		DOT11_SSID dot11Ssid = { 0 };
		memcpy(dot11Ssid.ucSSID, account, strlen(account) + 1);
		dot11Ssid.uSSIDLength = strlen(account);

		WLAN_CONNECTION_PARAMETERS connectionParameters;
		memset(&connectionParameters, 0, sizeof(connectionParameters));
		connectionParameters.pDot11Ssid = &dot11Ssid;
		connectionParameters.wlanConnectionMode = wlan_connection_mode_profile;
		connectionParameters.strProfile = wideSsid;   /* clear 可以填nullptr */
		connectionParameters.dot11BssType = dot11_BSS_type_any;//dot11_BSS_type_independent;  /* msdn说可以dot11_BSS_type_any,实测不行 */
		connectionParameters.pDesiredBssidList = nullptr;
		connectionParameters.dwFlags = 0; /* WLAN_CONNECTION_ADHOC_JOIN_ONLY */

		Sleep(300);

		value = WlanConnect(m_handle, &m_infoList->InterfaceInfo[0].InterfaceGuid,
			&connectionParameters, nullptr);
		if (value != ERROR_SUCCESS)
		{
			disconnect();
			sprintf(m_lastError, "连接WIFI失败,错误代码:%lu", value);
			break;
		}

		//value = WlanRegisterNotification(m_handle, WLAN_NOTIFICATION_SOURCE_ALL, false,
		//	wlanNotification, this, nullptr, nullptr);
		//if (value != ERROR_SUCCESS)
		//{
		//	sprintf(m_lastError, "注册通知失败,错误代码:%lu", value);
		//	break;
		//}
		m_connected = true;
		result = true;
	} while (false);
	return result;
}

bool WifiMgr::connect(const WifiInfo& info)
{
	return connect(info.account, info.password, info.mode, info.auth, info.encrypt);
}

bool WifiMgr::reconnect()
{
	bool result = false;
	m_reconnect = true;
	result = disconnect() && connect(m_wifiInfo);
	m_reconnect = false;
	return result;
}

bool WifiMgr::disconnect(bool removeProFile)
{
	bool result = true;
	do
	{
		unsigned long value = 0;

		if (removeProFile)
		{
			wchar_t profile[256] = { 0 };
			if (MultiByteToWideChar(CP_ACP, 0, m_wifiInfo.account, strlen(m_wifiInfo.account) + 1,
				profile, sizeof(profile) / sizeof(profile[0])))
			{
				if (m_handle != INVALID_HANDLE_VALUE && m_infoList)
				{
					WlanDeleteProfile(m_handle, &(m_infoList->InterfaceInfo->InterfaceGuid), profile, nullptr);
				}
			}
		}

		if (m_handle != INVALID_HANDLE_VALUE && m_infoList)
		{
			WlanDisconnect(m_handle, &(m_infoList->InterfaceInfo->InterfaceGuid), nullptr);
		}

		if (m_handle != INVALID_HANDLE_VALUE)
		{
			WlanCloseHandle(m_handle, nullptr);
			m_handle = INVALID_HANDLE_VALUE;
		}

		if (m_infoList)
		{
			WlanFreeMemory(m_infoList);
			m_infoList = nullptr;
		}
		m_connected = false;
	} while (false);
	return result;
}

bool WifiMgr::connected() const
{
	return m_connected;
}

const char* WifiMgr::getLastError() const
{
	return m_lastError;
}

void WifiMgr::wlanNotification(PWLAN_NOTIFICATION_DATA data, void* args)
{
	WifiMgr* wifi = static_cast<WifiMgr*>(args);
	if (!wifi)
		return;

	unsigned long source = data->NotificationSource;
	unsigned long code = data->NotificationCode;
	unsigned long size = data->dwDataSize;
	const char* action = "unknown";
	if (source == WLAN_NOTIFICATION_SOURCE_ACM)
	{
		switch (source)
		{
		case wlan_notification_acm_start:
			action = "acm_start";
			break;
		case wlan_notification_acm_autoconf_enabled:
			action = "acm_autoconf_enabled";
			break;
		case wlan_notification_acm_autoconf_disabled:
			action = "acm_autoconf_disabled";
			break;
		case wlan_notification_acm_background_scan_enabled:
			action = "acm_background_scan_enabled";
			break;
		case wlan_notification_acm_background_scan_disabled:
			action = "acm_background_scan_disabled";
			break;
		case wlan_notification_acm_bss_type_change:
			action = "acm_bss_type_change";
			break;
		case wlan_notification_acm_power_setting_change:
			action = "acm_power_setting_change";
			break;
		case wlan_notification_acm_scan_complete:
			action = "acm_scan_complete";
			break;
		case wlan_notification_acm_scan_fail:
			action = "acm_scan_fail";
			break;
		case wlan_notification_acm_connection_start:
			action = "acm_connection_start";
			break;
		case wlan_notification_acm_connection_complete:
			action = "acm_connection_complete";
			break;
		case wlan_notification_acm_connection_attempt_fail:
			action = "acm_connection_attempt_fail";
			break;
		case wlan_notification_acm_filter_list_change:
			action = "acm_filter_list_change";
			break;
		case wlan_notification_acm_interface_arrival:
			action = "acm_interface_removal";
			break;
		case wlan_notification_acm_interface_removal:
			action = "acm_interface_removal";
			break;
		case wlan_notification_acm_profile_change:
			action = "acm_profile_change";
			break;
		case wlan_notification_acm_profile_name_change:
			action = "acm_profile_name_change";
			break;
		case wlan_notification_acm_profiles_exhausted:
			action = "acm_profiles_exhausted";
			break;
		case wlan_notification_acm_network_not_available:
			action = "acm_network_not_available";
			break;
		case wlan_notification_acm_network_available:
			action = "acm_network_available";
			break;
		case wlan_notification_acm_disconnecting:
			action = "acm_disconnecting";
			break;
		case wlan_notification_acm_disconnected:
			action = "acm_disconnected";
			break;
		case wlan_notification_acm_adhoc_network_state_change:
			action = "acm_adhoc_network_state_change";
			break;
		case wlan_notification_acm_end:
			action = "acm_end";
			break;
		default:break;
		}
	}
	else if (source == WLAN_NOTIFICATION_SOURCE_MSM)
	{
		switch (code)
		{
		case wlan_notification_msm_start:
			action = "msm_start";
			break;
		case wlan_notification_msm_associating:
		{
			auto ptr = ((PWLAN_MSM_NOTIFICATION_DATA)data->pData);
		}
		action = "msm_associating";
		break;
		case wlan_notification_msm_associated:
		{
			auto ptr = ((PWLAN_MSM_NOTIFICATION_DATA)data->pData);
		}
		action = "msm_associated";
		break;
		case wlan_notification_msm_authenticating:
		{
			auto ptr = ((PWLAN_MSM_NOTIFICATION_DATA)data->pData);
		}
		action = "msm_authenticating";
		break;
		case wlan_notification_msm_connected:
			action = "msm_connected";
			break;
		case wlan_notification_msm_roaming_start:
			action = "msm_roaming_start";
			break;
		case wlan_notification_msm_roaming_end:
			action = "msm_roaming_end";
			break;
		case wlan_notification_msm_radio_state_change:
			action = "msm_radio_state_change";
			break;
		case wlan_notification_msm_signal_quality_change:
			action = "msm_signal_quality_change";
			printf("信号质量:%lu\n", *(unsigned long*)data->pData);
			break;
		case wlan_notification_msm_disassociating:
			action = "msm_disassociating";
			break;
		case wlan_notification_msm_disconnected:
		{
			auto ptr = ((PWLAN_MSM_NOTIFICATION_DATA)data->pData);
		}
		action = "msm_disconnected";
		break;
		case wlan_notification_msm_peer_join:
			action = "msm_peer_join";
			break;
		case wlan_notification_msm_peer_leave:
			action = "msm_peer_leave";
			break;
		case wlan_notification_msm_adapter_removal:
			action = "msm_adapter_removal";
			break;
		case wlan_notification_msm_adapter_operation_mode_change:
			action = "msm_adapter_operation_mode_change";
			break;
		case wlan_notification_msm_end:
			action = "msm_end";
			break;
		default:break;
		}
	}
	printf("source %d,code %d,size %d,action %s\n", source, code, size, action);
	return;
}

  • 4
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
要在 C++ 中实现自动连接 WiFi,可以使用 Windows API 函数来执行以下步骤: 1. 初始化 WLAN API。 2. 枚举可用的 WiFi 网络。 3. 遍历可用的 WiFi 网络列表,找到目标网络。 4. 创建配置文件以连接目标网络。 5. 连接目标网络。 下面是一个基本的 C++ 代码示例,用于自动连接名为“myWiFi”的 WiFi 网络: ```c++ #include <windows.h> #include <wlanapi.h> #include <wtypes.h> #include <objbase.h> #include <stdio.h> #pragma comment(lib, "wlanapi.lib") #pragma comment(lib, "ole32.lib") int main() { // 初始化 WLAN API DWORD dwClientVersion = 0; DWORD dwRetVal = 0; HANDLE hClient = NULL; PWLAN_INTERFACE_INFO_LIST pIfList = NULL; PWLAN_INTERFACE_INFO pIfInfo = NULL; DWORD dwMaxClient = 2; // 最大连接数 DWORD dwCurVersion = 0; dwRetVal = WlanOpenHandle(dwMaxClient, NULL, &dwClientVersion, &hClient); if (dwRetVal != ERROR_SUCCESS) { printf("WlanOpenHandle failed with error: %u\n", dwRetVal); return 1; } dwRetVal = WlanEnumInterfaces(hClient, NULL, &pIfList); if (dwRetVal != ERROR_SUCCESS) { printf("WlanEnumInterfaces failed with error: %u\n", dwRetVal); return 1; } // 遍历 WiFi 网络列表 for (DWORD i = 0; i < pIfList->dwNumberOfItems; i++) { pIfInfo = (WLAN_INTERFACE_INFO *)&pIfList->InterfaceInfo[i]; // 枚举可用的 WiFi 网络 PWLAN_AVAILABLE_NETWORK_LIST pAvailableNetworkList = NULL; dwRetVal = WlanGetAvailableNetworkList(hClient, &pIfInfo->InterfaceGuid, 0, NULL, &pAvailableNetworkList); if (dwRetVal != ERROR_SUCCESS) { printf("WlanGetAvailableNetworkList failed with error: %u\n", dwRetVal); return 1; } // 遍历可用的 WiFi 网络列表,找到目标网络 for (DWORD j = 0; j < pAvailableNetworkList->dwNumberOfItems; j++) { WLAN_AVAILABLE_NETWORK *pAvailableNetwork = &pAvailableNetworkList->Network[j]; if (strcmp((char *)pAvailableNetwork->dot11Ssid.ucSSID, "myWiFi") == 0) { // 创建配置文件以连接目标网络 WLAN_CONNECTION_PARAMETERS wlanConnectionParams; wlanConnectionParams.wlanConnectionMode = wlan_connection_mode_profile; wlanConnectionParams.strProfile = (LPCWSTR)L"myWiFi"; wlanConnectionParams.pDot11Ssid = &pAvailableNetwork->dot11Ssid; wlanConnectionParams.pDesiredBssidList = NULL; wlanConnectionParams.dot11BssType = pAvailableNetwork->dot11BssType; wlanConnectionParams.dwFlags = 0; dwRetVal = WlanConnect(hClient, &pIfInfo->InterfaceGuid, &wlanConnectionParams, NULL); if (dwRetVal != ERROR_SUCCESS) { printf("WlanConnect failed with error: %u\n", dwRetVal); return 1; } } } WlanFreeMemory(pAvailableNetworkList); } WlanFreeMemory(pIfList); WlanCloseHandle(hClient, NULL); return 0; } ``` 请注意,此代码示例仅适用于 Windows 操作系统。在其他操作系统上,需要使用相应的 API 函数来执行相同的任务。此外,还需要在程序中引用相应的库文件。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值