How to determine MAC Address of the actual physical network card — not virtual network interfaces created by VPN's (.NET C#)

你离开我真会死。 提交于 2019-11-27 07:38:11
Sergey

This is my method: it uses the fact that physical card is connected to PCI interface

ManagementObjectSearcher searcher = new ManagementObjectSearcher
    ("Select MACAddress,PNPDeviceID FROM Win32_NetworkAdapter WHERE MACAddress IS NOT NULL AND PNPDeviceID IS NOT NULL");
ManagementObjectCollection mObject = searcher.Get();

foreach (ManagementObject obj in mObject)
{
    string pnp = obj["PNPDeviceID"].ToString();
    if (pnp.Contains("PCI\\"))
    {
        string mac = obj["MACAddress"].ToString();
        mac = mac.Replace(":", string.Empty);
        return mac;
    }
}

The first three bytes of the MAC address are a manufacturer ID. You could blacklist certain manufacturer IDs known to be unsuitable for your purposes, and ignore those interfaces.

Relying on the speed is not likely to be a good idea, because there's no reason why a VPN interface couldn't report itself as having gigabit speed.

MAC addresses are physical hardware addresses. I can't test on this pc, but I don't think you will get a new MAC address if a virtual connection is added because it's not an actual piece of hardware. It will be another connection, but not another MAC address.

So guaranteeing that you get the same MAC address every time depends on the same pieces of hardware being attached to the machine and you using the same algorithm to pick from that hardware.

I've been looking at this problem as well, and believe that without persistent state it's going to be difficult to maintain a stable MAC.

The solution I'm toying with is take the first NIC found in the adapter order and use that and save it. Then on subsequent UUID generations, use the saved MAC if it's found anywhere in the stack even if not the first. This way the adapter order can move around and we don't worry about blowing up whatever depends on the stable MAC (such as a licensing module).

If the saved MAC is not found in the stack, it's discarded and we just use the first MAC in the binding order and start over.

 public static string GetMacAddressPhysicalNetworkInterface()
    {

        ManagementObjectSearcher searcher = new ManagementObjectSearcher
        ("Select MACAddress,PNPDeviceID FROM Win32_NetworkAdapter WHERE MACAddress IS NOT NULL AND" +
         " PNPDeviceID IS NOT NULL AND" +
         " PhysicalAdapter = true");
        ManagementObjectCollection mObject = searcher.Get();

        string macs = (from ManagementObject obj in mObject
                let pnp = obj["PNPDeviceID"].ToString()
                where !(pnp.Contains("ROOT\\"))
                //where  pnp.Contains("PCI\\")  || pnp.Contains("USB\\")
                select obj).Select(obj => obj["MACAddress"].ToString())
            .Aggregate<string, string>(null, (mac, currentMac) => mac + currentMac.Replace(":", string.Empty) + ",");

        return !string.IsNullOrEmpty(macs) ? macs.Substring(0, macs.Length - 1) : macs;
    }

    public static NetworkInterface GetPhysicalNetworkInterface(string macAddressPhysicalNetworkInterface)
    {
        return NetworkInterface.GetAllNetworkInterfaces().FirstOrDefault(currentNetworkInterface => string.Equals(currentNetworkInterface.GetPhysicalAddress().ToString(), macAddressPhysicalNetworkInterface, StringComparison.CurrentCultureIgnoreCase));
    }
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!