21

背景

我正在尝试从计算机中获取唯一标识符,并希望每次都能可靠地返回相同的 MAC 地址。相信我,我有使用 MAC 地址的理由,并且阅读了许多关于替代唯一 ID 方法的帖子(是的,我考虑过他们是否没有任何网卡)。

问题

问题出在 .NET 中,无论如何我都看不到特定的 NetworkInterface 是否是来自诸如“Nortel IPSECSHM 适配器 - 数据包调度程序微型端口”之类的物理硬件网卡,当您连接到某些 VPN 或 WiFi 网络时,会添加这些网卡。

我知道如何使用与此类似的代码来获取 Mac 地址:

    foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces())
    {
        log.Debug("NIC " + nic.OperationalStatus + " " + nic.NetworkInterfaceType + " " + nic.Speed + " " + nic.GetPhysicalAddress() + " " + nic.Description);
    }

可以理解的是,没有 100% 的方法来确保我会得到一个内部网卡,但我想选择 MAC 地址来返回给定机器最不可能改变的 MAC 地址。独立于诸如 - 它是否连接到 wifi ......通过某种类型的系绳连接......或者他们安装了一些新的 vpn 软件来添加新界面。

考虑的策略

1) 选择第一个界面为“Up”。这在我的笔记本电脑上失败了,因为“数据包微型端口”始终处于启动状态。此外,如果我将手机连接到笔记本电脑,这也会显示为第一张卡。

2)选择最合适的类型......这失败了b / c基本上所有东西都显示为“以太网”,包括WiFi适配器和我的iPHone网络共享互联网连接。

3) 选择具有 IP 地址的 NIC。失败有几个原因:1)网卡可能没有连接到 LAN 2)有多个网卡可能有 IP 地址。

4)只需发送所有MAC地址...问题是列表会根据安装的软件而变化,并且很难比较。

5)选择速度最快的mac地址。我想这可能是我最好的选择。我认为可以肯定地说,最快的界面通常是最永久的。

或者,可能有其他方法可以检测 .NET 中的物理卡,或者如果您可以推荐一种可以提供不同信息的 API 调用,我会考虑调用其他 API 调用。

还有其他想法吗?

在这里演示的是当我将我的 iphone 拴在上面时我的示例代码的输出:

DEBUG - NIC Down Ethernet 500000     0021E98BFBEF Apple Mobile Device Ethernet - Packet Scheduler Miniport
DEBUG - NIC Up   Ethernet 10000000   444553544200 Nortel IPSECSHM Adapter - Packet Scheduler Miniport
DEBUG - NIC Down Ethernet 54000000   00166FAC94C7 Intel(R) PRO/Wireless 2200BG Network Connection - Packet Scheduler Miniport
DEBUG - NIC Down Ethernet 1000000000 0016D326E957 Broadcom NetXtreme Gigabit Ethernet - Packet Scheduler Miniport
DEBUG - NIC Up   Loopback 10000000  MS TCP Loopback interface

未连接 Iphone:

DEBUG - NIC Up   Ethernet 10000000   444553544200 Nortel IPSECSHM Adapter - Packet Scheduler Miniport
DEBUG - NIC Down Ethernet 54000000   00166FAC94C7 Intel(R) PRO/Wireless 2200BG Network Connection - Packet Scheduler Miniport
DEBUG - NIC Down Ethernet 1000000000 0016D326E957 Broadcom NetXtreme Gigabit Ethernet - Packet Scheduler Miniport
DEBUG - NIC Up   Loopback 10000000  MS TCP Loopback interface
4

5 回答 5

12

这是我的方法:它使用物理卡连接到 PCI 接口的事实

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;
    }
}
于 2010-08-20T11:23:01.897 回答
2

MAC 地址的前三个字节是制造商 ID。您可以将某些已知不适合您的目的的制造商 ID 列入黑名单,并忽略这些接口。

依靠速度可能不是一个好主意,因为 VPN 接口没有理由不能报告自己具有千兆速度。

于 2009-10-14T22:31:39.373 回答
0

MAC 地址是物理硬件地址。我无法在这台电脑上进行测试,但我认为如果添加虚拟连接,您将不会获得新的 MAC 地址,因为它不是实际的硬件。这将是另一个连接,但不是另一个 MAC 地址。

因此,确保您每次都获得相同的 MAC 地址取决于连接到机器的相同硬件,并且您使用相同的算法从该硬件中进行选择。

于 2009-10-14T18:43:36.897 回答
0

我也一直在研究这个问题,并相信如果没有持久状态,就很难维持稳定的 MAC。

我正在玩弄的解决方案是获取在适配器订单中找到的第一个 NIC,然后使用它并保存它。然后在后续的 UUID 生成中,如果在堆栈中的任何位置找到保存的 MAC,即使不是第一个,也要使用它。这样适配器订单可以移动,我们不用担心会炸毁任何依赖于稳定 MAC 的东西(例如许可模块)。

如果在堆栈中找不到保存的 MAC,则将其丢弃,我们只需使用绑定顺序中的第一个 MAC 并重新开始。

于 2012-12-28T16:15:06.410 回答
0
 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));
    }
于 2017-08-23T07:06:50.247 回答