본문 바로가기
Development/.NET

[.NET] C# Mac Address 추출 시 유의사항

by Kyunghoon Kim 2024. 6. 15.

 윈도우 기반에서 동작하는 하드웨어나 여러 장치들을 연동하여 개발하다 보면 고유 주소인 맥어드레스(MacAddress)가 필요한 경우가 있습니다. 맥어드레스는 명령 프롬프트(CMD)에서 ipconfig /all 명령 이용하면 쉽게 확인할 수 있습니다.

 

ipconfig /all

 

그렇다면 C#에서 이 맥어드레스는 어떻게 추출할 수 있을까요? 추출하는 방법은 여러 가지가 있을 수 있습니다. CMD 또는 PowerShell 명령 수행 후 출력된 결과를 읽어와서 데이터를 가공해 처리할 수도 있고, NetworkInterface 또는 WMI (Windows Management Instrumentation) 쿼리를 이용해 WMI 저장소에서 정보를 가져올 수도 있습니다.

 

 저는 키오스크 개발을 할 때 WMI 쿼리를 이용해 네트워크 어댑터의 구성 정보를 추출하는 방식을 사용했었는데요 최근 해당 방식으로 맥어드레스를 추출하는 부분에 문제가 발생하여 운영 환경에 나가 있던 키오스크 사용에 문제가 발생한 적이 있습니다.

 

일부 극소수의 윈도우 환경에서 WMI가 손상되어 맥어드레스가 제대로 추출되지 않는 문제가 있었고 당연하게도 이 맥어드레스를 이용하는 로직에 문제가 발생했습니다. WMI가 손상된 경우 복구를 할 수 있는 방법이 존재하긴 하지만, 해당 방법으로도 복구가 완전히 이루어지지 않는 환경이 존재했기 때문에 다른 방법을 찾아야 했습니다.

 

string macAddress = string.Empty;

ManagementObjectSearcher managementObjectSearcher = new ManagementObjectSearcher("select * from Win32_NetworkAdapterConfiguration where IPEnabled = 'True'");
foreach (ManagementObject managementObject in managementObjectSearcher.Get())
{
    macAddress = managementObject["MACAddress"].ToString();
    break;
}

WMI 쿼리를 이용한 맥어드레스 추출

 

 맥어드레스를 추출하는 또 다른 방법인 NetworkInterface를 이용할 건데요 여기서 WMI 쿼리로 추출하는 맥어드레스와 일반적으로 흔히 검색하면 찾아볼 수 있는 NetworkInterface를 이용하는 방식에는 큰 차이점이 있습니다.

 

 WMI로 조회되는 정보는 "IP가 활성화된 네트워크 어댑터의 MAC 주소"를 반환하고, NetworkInterface의 경우 "활성화된 네트워크 인터페이스 중 첫 번째 인터페이스의 MAC 주소"를 반환합니다.

 

 즉 내가 현재 추출하고자 하는 장비의 맥어드레스가 아니라 내 PC의 장비 목록 중에서 활성화된 네트워크 인터페이스의 첫 번째 맥어드레스를 사용하는 꼴이 됩니다. (지금 필요한 것은 현재 IP 주소에 대응되는 맥어드레스)

 

var macAddress = (from networkInterface in NetworkInterface.GetAllNetworkInterfaces()
                  where networkInterface.OperationalStatus == OperationalStatus.Up
                  select networkInterface.GetPhysicalAddress().GetAddressBytes()).FirstOrDefault();

return string.Join(":", (from z in macAddress select z.ToString("X2")).ToArray());

NetworkInterface를 이용한 맥어드레스 추출

 

 그렇다면 NetworkInterface로 활성화된 네트워크 중에서 내가 필요로 하는 장비의 맥어드레스를 어떻게 가져올 수 있을까요? 

 

var networkInterfaces = NetworkInterface.GetAllNetworkInterfaces()
     .Where(nic => nic.OperationalStatus == OperationalStatus.Up)
     .ToList();

string platformIp = string.Empty;
string platformGateway = string.Empty;

foreach (NetworkInterface networkInterface in networkInterfaces)
{
    var ipProperties = networkInterface.GetIPProperties();
    var gatewayAddress = ipProperties.GatewayAddresses
        .Select(g => g.Address)
        .FirstOrDefault();

    if (networkInterface.NetworkInterfaceType == NetworkInterfaceType.Wireless80211)
    {
        platformIp = ipProperties.UnicastAddresses[1].Address.ToString();
        platformGateway = gatewayAddress.ToString() ?? string.Empty;
        break;
    }
}

foreach (NetworkInterface networkInterface in networkInterfaces)
{
    foreach (UnicastIPAddressInformation unicastIPAddressInformation in networkInterface.GetIPProperties().UnicastAddresses)
    {
        if (unicastIPAddressInformation.Address.AddressFamily == AddressFamily.InterNetwork)
        {
            if (IPAddress.Parse(platformIp).Equals(unicastIPAddressInformation.Address))
            {
                var macAddressBytes = networkInterface.GetPhysicalAddress().GetAddressBytes();
                var macAddress = string.Join(":", macAddressBytes.Select(b => b.ToString("X2"))));
            }
        }
    }
}

 

 네트워크 인터페이스 목록에서 인터페이스가 무선 LAN 연결platformIp 주소와 platformGateway 주소를 추출한 뒤 IP 버전 4.에 대응되는 것을 찾아 형식에 맞게 변환해 주면 필요한 맥어드레스를 추출할 수 있게 됩니다.

 

구글링을 통해 흔히 찾아볼 수 있는 WMI 쿼리 방식과 NetworkInterface 방식을 사용하되 두 방식의 차이점을 이해하고 본인에게 필요한 부분을 가공하여 사용하는 게 중요할 것 같습니다.

댓글