我们经常会在代码中查找设备的Mac地址,以确认设备的唯一性。但是如果你的设备安装了一些虚拟机,这个时候就会比较麻烦了


出现问题

看一下我这边通过ipconfig /all 跑出来的结果,大家猜猜看,哪个才是我的物理网卡呢?

1563355703024

看名称?看描述,看NetBIOS启用状态?唉,都不靠谱,你能想到是第一个标着fake_wlan,描述带Hyper-V的才是我的物理网卡么?

How

那么如何才能去找到我们的物理网卡信息呢?

OK,首先的一个问题是如何找到网卡信息。德熙这边的博客有介绍了dotnet core 获取 MacAddress 地址方法,不过很不巧这里面没有介绍虚拟网卡和物理网卡的区分方法。

不过,德熙的博客里面介绍了使用WMI,查询Win32_NetworkAdapterConfiguration的方式找到网络适配器的信息。对于系统来说物理网卡和虚拟网卡的Win32_NetworkAdapterConfiguration是没有区别的,所以这里我们看不出分别(Ipconfig也是如此)

但是WMI有另外一个信息叫做,Win32_NetworkAdapter,他包含了网络适配器的信息。

而这个信息中最关键的两点是NetConnectionStatusPNPDeviceID,前者代表了网络连接状态,可以过滤哪些不在上网的设备,后者更为重要,表示设备实例路径,就是下面这个家伙

1563356920923

设备实例路径有什么用呢?小Track就是物理网卡的设备实例路径都是以”PCI”开头的,(当然你要说厂家喜欢乱来,或者自己把里面的内容改了,那我也没有办法)。

OK,有了这些知识,我们写代码就很方便了。

额,不完全是。这个其实是跟点击其他程序窗口这一操作有关。其实你只要启动时点击其他窗口的手速够快,也能出现。

我们看看MessageBox的源码。当我们采用MessageBox.Show方法重载不带有owner参数时,他会通过GetActiveWindow这个方法获取当前激活的窗口,作为owner。而我们通过只要在程序执行到这里之前点击其他程序窗口,就会出现上述问题

1563249678194

        static string Bar()
        {
            var managementClass = new ManagementClass("Win32_NetworkAdapter");
            var managementObjectCollection = managementClass.GetInstances();
            var builder = new StringBuilder();
            foreach (var managementObject in managementObjectCollection.OfType<ManagementObject>())
            {
                using (managementObject)
                {
                    if (managementObject["NetConnectionStatus"] != null
                        &&  managementObject["NetConnectionStatus"].ToString() == "2"
                        && managementObject["PNPDeviceID"].ToString().Contains("PCI"))
                    {
                        if (managementObject["MacAddress"] == null)
                        {
                            continue;
                        }

                        builder.AppendLine(managementObject["MacAddress"].ToString().ToUpper());
                    }
                }
            }

            return builder.ToString();
        }

结果如下,只剩下一个1C开头的我们的物理网卡的Mac地址了

1563357224333

参考链接:


本文会经常更新,请阅读原文: https://xinyuehtx.github.io/post/%E4%B8%BA%E4%BB%80%E4%B9%88MessageBox%E4%BC%9A%E8%B7%91%E5%88%B0%E7%AA%97%E5%8F%A3%E4%B8%8B%E9%9D%A2.html ,以避免陈旧错误知识的误导,同时有更好的阅读体验。

知识共享许可协议 本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名黄腾霄(包含链接: https://xinyuehtx.github.io ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请 与我联系