현재 연결된 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;
}


위의 코드를 실행하게 되면 아래와 같이 오류가 발생한다.

image



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

image



실습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;
}


코드를 실행해보면 아래와 같은 에러가 뜬다.

image


이 에러는 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

image



실습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;
        }
    }    
}

결과3

image