현재 연결된 WiFi
- 최초 작성일: 2023년 2월 17일 (금)
목차
[TOC]
내용
시스템 커맨드인 “netsh wlan show profiles” 로 나온 결과 중,
현재 연결 중인 와이파이와 일치하는 사용자 프로필을 뽑고자 한다.
실습1
#include <iostream>
#include <Windows.h>
#include <wlanapi.h>
#include <objbase.h>
#include <wtypes.h>
#include <string>
#include <vector>
#pragma comment(lib, "Wlanapi.lib")
#pragma comment(lib, "ole32.lib")
std::wstring ConvertWCharToString(const WCHAR* wstr) {
std::wstring str(wstr);
return str;
}
int main() {
DWORD negotiatedVersion;
HANDLE clientHandle = NULL;
// Initialize the handle to the WLAN client.
DWORD ret = WlanOpenHandle(2, NULL, &negotiatedVersion, &clientHandle);
if (ret != ERROR_SUCCESS) {
std::cerr << "WlanOpenHandle failed with error: " << ret << std::endl;
return 1;
}
PWLAN_INTERFACE_INFO_LIST ifList = NULL;
ret = WlanEnumInterfaces(clientHandle, NULL, &ifList);
if (ret != ERROR_SUCCESS) {
std::cerr << "WlanEnumInterfaces failed with error: " << ret << std::endl;
return 1;
}
for (DWORD i = 0; i < ifList->dwNumberOfItems; i++) {
PWLAN_INTERFACE_INFO pIfInfo = &ifList->InterfaceInfo[i];
PWLAN_CONNECTION_ATTRIBUTES pConnectInfo = NULL;
// Get the current connection attributes.
ret = WlanQueryInterface(clientHandle, &pIfInfo->InterfaceGuid, wlan_intf_opcode_current_connection, NULL,
(PDWORD)&pConnectInfo, (PVOID)&pConnectInfo, NULL);
if (ret != ERROR_SUCCESS) {
std::cerr << "WlanQueryInterface failed with error: " << ret << std::endl;
continue;
}
std::wcout << "Currently connected to: " << ConvertWCharToString(pConnectInfo->strProfileName) << std::endl;
std::wcout << "Other profiles available: " << std::endl;
PWLAN_PROFILE_INFO_LIST profileList = NULL;
ret = WlanGetProfileList(clientHandle, &pIfInfo->InterfaceGuid, NULL, &profileList);
if (ret != ERROR_SUCCESS) {
std::cerr << "WlanGetProfileList failed with error: " << ret << std::endl;
continue;
}
for (DWORD j = 0; j < profileList->dwNumberOfItems; j++) {
PWLAN_PROFILE_INFO profileInfo = &profileList->ProfileInfo[j];
std::wstring profileName = ConvertWCharToString(profileInfo->strProfileName);
if (profileName != ConvertWCharToString(pConnectInfo->strProfileName)) {
std::wcout << "- " << profileName << std::endl;
}
}
WlanFreeMemory(pConnectInfo);
WlanFreeMemory(profileList);
}
WlanFreeMemory(ifList);
WlanCloseHandle(clientHandle, NULL);
return 0;
}
위의 코드를 실행하게 되면 아래와 같이 오류가 발생한다.
WlanQueryInterface() 함수는 다음과 같은 인자를 받는다.
DWORD WlanQueryInterface(
HANDLE hClientHandle,
const GUID *pInterfaceGuid,
WLAN_INTF_OPCODE OpCode,
PVOID pReserved,
PDWORD pdwDataSize,
PVOID *ppData,
PWLAN_OPCODE_VALUE_TYPE pWlanOpcodeValueType
);
// Get the current connection attributes.
ret = WlanQueryInterface(clientHandle, &pIfInfo->InterfaceGuid, wlan_intf_opcode_current_connection, NULL,
(PDWORD)&pConnectInfo, (PVOID)&pConnectInfo, NULL);
하지만 현재 코드에서는 인자를 6개를 넘겨줬기 때문에 발생한 오류이다.
함수 호출부분에서 넘겨주는 인자를 아래와 같이 수정해주면 된다.
// Get the current connection attributes.
ret = WlanQueryInterface(
clientHandle,
&pIfInfo->InterfaceGuid,
wlan_intf_opcode_current_connection,
NULL,
(PDWORD)&pConnectInfo,
(PVOID*)&pConnectInfo,
NULL);
풀소스
실행시 현재 연결된 와이파이와 해당 와이파이를 사용하는 다른 사용자 프로필 이름이 출력된다.
#include <iostream>
#include <Windows.h>
#include <wlanapi.h>
#include <objbase.h>
#include <wtypes.h>
#include <string>
#include <vector>
#pragma comment(lib, "Wlanapi.lib")
#pragma comment(lib, "ole32.lib")
std::wstring ConvertWCharToString(const WCHAR* wstr) {
std::wstring str(wstr);
return str;
}
int main() {
DWORD negotiatedVersion;
HANDLE clientHandle = NULL;
// Initialize the handle to the WLAN client.
DWORD ret = WlanOpenHandle(2, NULL, &negotiatedVersion, &clientHandle);
if (ret != ERROR_SUCCESS) {
std::cerr << "WlanOpenHandle failed with error: " << ret << std::endl;
return 1;
}
PWLAN_INTERFACE_INFO_LIST ifList = NULL;
ret = WlanEnumInterfaces(clientHandle, NULL, &ifList);
if (ret != ERROR_SUCCESS) {
std::cerr << "WlanEnumInterfaces failed with error: " << ret << std::endl;
return 1;
}
for (DWORD i = 0; i < ifList->dwNumberOfItems; i++) {
PWLAN_INTERFACE_INFO pIfInfo = &ifList->InterfaceInfo[i];
PWLAN_CONNECTION_ATTRIBUTES pConnectInfo = NULL;
// Get the current connection attributes.
ret = WlanQueryInterface(
clientHandle,
&pIfInfo->InterfaceGuid,
wlan_intf_opcode_current_connection,
NULL,
(PDWORD)&pConnectInfo,
(PVOID*)&pConnectInfo,
NULL);
if (ret != ERROR_SUCCESS) {
std::cerr << "WlanQueryInterface failed with error: " << ret << std::endl;
continue;
}
std::wcout << "Currently connected to: " << ConvertWCharToString(pConnectInfo->strProfileName) << std::endl;
std::wcout << "Other profiles available: " << std::endl;
PWLAN_PROFILE_INFO_LIST profileList = NULL;
ret = WlanGetProfileList(clientHandle, &pIfInfo->InterfaceGuid, NULL, &profileList);
if (ret != ERROR_SUCCESS) {
std::cerr << "WlanGetProfileList failed with error: " << ret << std::endl;
continue;
}
for (DWORD j = 0; j < profileList->dwNumberOfItems; j++) {
PWLAN_PROFILE_INFO profileInfo = &profileList->ProfileInfo[j];
std::wstring profileName = ConvertWCharToString(profileInfo->strProfileName);
if (profileName != ConvertWCharToString(pConnectInfo->strProfileName)) {
std::wcout << "- " << profileName << std::endl;
}
}
WlanFreeMemory(pConnectInfo);
WlanFreeMemory(profileList);
}
WlanFreeMemory(ifList);
WlanCloseHandle(clientHandle, NULL);
return 0;
}
결과1
실습2
하지만 여기서, 필자 같은 경우는 와이파이 동글을 사용하여 동시에 2개의 와이파이가 연결하므로, 해당 와이파이들의 모든 사용자 프로필을 얻고자 한다.
아래는 현재 연결된 와이파이의 사용자 프로필만 출력하는 C++ 코드이다.
현재 연결된 와이파이의 사용자 프로필 이름을 가져오고, 이를 기준으로 전체 사용자 프로필 중 연결된 와이파이의 사용자 프로필만 출력하는 방식을 사용했다.
#include <iostream>
#include <Windows.h>
#include <wlanapi.h>
#include <objbase.h>
#include <wtypes.h>
#include <string>
#pragma comment(lib, "Wlanapi.lib")
#pragma comment(lib, "ole32.lib")
std::wstring ConvertWCharToString(const WCHAR* wstr) {
std::wstring str(wstr);
return str;
}
int main() {
DWORD negotiatedVersion;
HANDLE clientHandle = NULL;
// Initialize the handle to the WLAN client.
DWORD ret = WlanOpenHandle(2, NULL, &negotiatedVersion, &clientHandle);
if (ret != ERROR_SUCCESS) {
std::cerr << "WlanOpenHandle failed with error: " << ret << std::endl;
return 1;
}
PWLAN_INTERFACE_INFO_LIST ifList = NULL;
ret = WlanEnumInterfaces(clientHandle, NULL, &ifList);
if (ret != ERROR_SUCCESS) {
std::cerr << "WlanEnumInterfaces failed with error: " << ret << std::endl;
return 1;
}
for (DWORD i = 0; i < ifList->dwNumberOfItems; i++) {
PWLAN_INTERFACE_INFO pIfInfo = &ifList->InterfaceInfo[i];
PWLAN_CONNECTION_ATTRIBUTES pConnectInfo = NULL;
// Get the current connection attributes.
ret = WlanQueryInterface(clientHandle, &pIfInfo->InterfaceGuid, wlan_intf_opcode_current_connection, NULL,
(PDWORD)&pConnectInfo, NULL);
if (ret != ERROR_SUCCESS) {
continue;
}
std::wstring connectedProfileName = ConvertWCharToString(pConnectInfo->strProfileName);
std::cout << "Connected WiFi profile: " << connectedProfileName << std::endl;
WlanFreeMemory(pConnectInfo);
PWLAN_PROFILE_INFO_LIST pProfileList = NULL;
ret = WlanGetProfileList(clientHandle, &pIfInfo->InterfaceGuid, NULL, &pProfileList);
if (ret == ERROR_SUCCESS) {
for (DWORD j = 0; j < pProfileList->dwNumberOfItems; j++) {
PWLAN_PROFILE_INFO pProfileInfo = &pProfileList->ProfileInfo[j];
std::wstring profileName = ConvertWCharToString(pProfileInfo->strProfileName);
if (profileName == connectedProfileName) {
std::cout << "Matched connected WiFi profile: " << profileName << std::endl;
}
}
WlanFreeMemory(pProfileList);
}
}
WlanFreeMemory(ifList);
WlanCloseHandle(clientHandle, NULL);
return 0;
}
코드를 실행해보면 아래와 같은 에러가 뜬다.
이 에러는 std::wstring 타입의 값에 대해 « 연산자를 지원하지 않는 것으로 보인다. 이를 해결하기 위해서는 std::wstring 타입을 출력 가능한 형태로 변환하는 방법을 사용하면 된다.
예를 들어, std::wcout 스트림을 사용하여 std::wstring 값을 출력하거나, std::wstringstream을 사용하여 std::wstring 값을 문자열로 변환하는 방법이 있다. 아래는 std::wstringstream을 사용하여 std::wstring 값을 출력하는 코드 예시이다.
std::wstring str = L"example";
std::wstringstream ss;
ss << str;
std::wcout << ss.str() << std::endl;
위 코드는 std::wstring 값을 std::wstringstream 객체에 넣어 문자열로 변환한 후, std::wcout 스트림을 사용하여 출력하는 방식으로 동작한다.
이를 참고하여 코드를 수정해보자. 사실 std::cout 을 std::wcout 으로만 바꿔주면 된다.
풀 소스
#include <iostream>
#include <Windows.h>
#include <wlanapi.h>
#include <objbase.h>
#include <wtypes.h>
#include <string>
#pragma comment(lib, "Wlanapi.lib")
#pragma comment(lib, "ole32.lib")
std::wstring ConvertWCharToString(const WCHAR* wstr) {
std::wstring str(wstr);
return str;
}
int main() {
DWORD negotiatedVersion;
HANDLE clientHandle = NULL;
// Initialize the handle to the WLAN client.
DWORD ret = WlanOpenHandle(2, NULL, &negotiatedVersion, &clientHandle);
if (ret != ERROR_SUCCESS) {
std::cerr << "WlanOpenHandle failed with error: " << ret << std::endl;
return 1;
}
PWLAN_INTERFACE_INFO_LIST ifList = NULL;
ret = WlanEnumInterfaces(clientHandle, NULL, &ifList);
if (ret != ERROR_SUCCESS) {
std::cerr << "WlanEnumInterfaces failed with error: " << ret << std::endl;
return 1;
}
for (DWORD i = 0; i < ifList->dwNumberOfItems; i++) {
PWLAN_INTERFACE_INFO pIfInfo = &ifList->InterfaceInfo[i];
PWLAN_CONNECTION_ATTRIBUTES pConnectInfo = NULL;
// Get the current connection attributes.
ret = WlanQueryInterface(
clientHandle,
&pIfInfo->InterfaceGuid,
wlan_intf_opcode_current_connection,
NULL,
(PDWORD)&pConnectInfo,
(PVOID*)&pConnectInfo,
NULL);
if (ret != ERROR_SUCCESS) {
continue;
}
std::wstring connectedProfileName = ConvertWCharToString(pConnectInfo->strProfileName);
std::wcout << "Connected WiFi profile: " << connectedProfileName << std::endl;
WlanFreeMemory(pConnectInfo);
PWLAN_PROFILE_INFO_LIST pProfileList = NULL;
ret = WlanGetProfileList(clientHandle, &pIfInfo->InterfaceGuid, NULL, &pProfileList);
if (ret == ERROR_SUCCESS) {
for (DWORD j = 0; j < pProfileList->dwNumberOfItems; j++) {
PWLAN_PROFILE_INFO pProfileInfo = &pProfileList->ProfileInfo[j];
std::wstring profileName = ConvertWCharToString(pProfileInfo->strProfileName);
if (profileName == connectedProfileName) {
std::wcout << "Matched connected WiFi profile: " << profileName << std::endl;
}
}
WlanFreeMemory(pProfileList);
}
}
WlanFreeMemory(ifList);
WlanCloseHandle(clientHandle, NULL);
return 0;
}
결과2
실습3
그렇게 뽑은 프로필 리스트 중 원하는 것만 뽑아내보자.
for (DWORD j = 0; j < pProfileList->dwNumberOfItems; j++) {
PWLAN_PROFILE_INFO pProfileInfo = &pProfileList->ProfileInfo[j];
std::wstring profileName = ConvertWCharToString(pProfileInfo->strProfileName);
if (profileName == connectedProfileName) {
std::wcout << "Matched connected WiFi profile: " << profileName << std::endl;
// Select profiles that start with "WAVE"
if (profileName.compare(0, 6, L"VISION") == 0) {
std::wcout << "Selected profile: " << profileName << std::endl;
}
}
}