通过WMI确定网络适配器类型

13

我正在使用WMI(Win32_NetworkAdapter)并尝试获取已连接的物理网络适配器的详细信息,无论是有线还是无线,并避免虚拟适配器等。

阅读这篇文章,它解释了您必须在WMI上进行一些巧妙的查询来消除虚拟适配器,并尝试仅返回真正的物理适配器。

阅读这篇帖子,它解释了您可以比较网络适配器的“描述”中的文本,以查看它是否包含“Wireless”、“802.11”或“WLAN”,如果是,则最可能的适配器是无线适配器。

随着今天的.Net版本和其他进步,这些是否真的是在Windows XP+上确定网络适配器是有线还是无线并且不是来自VM软件或类似软件的虚拟适配器的唯一两种方法? 如果不是,请解释。


1
你只是在寻找涉及 WMI 的解决方案吗? - M.Babcock
最好是这样。我的现有项目使用WMI和.Net相当广泛地获取适配器信息。如果有其他选项,我想知道,但不确定是否会实施。 - ScottN
使用WMI,你可以基于Win32_NetworkAdapter.PhysicalAdapter进行过滤(如果接口是虚拟的,则应为false),然后使用AdapterTypeID来确定它是有线还是无线的。我浏览了你发布的文章,他们的标准不合理。 - M.Babcock
Win32_NetworkAdapter.PhysicalAdapter Windows Server 2003、Windows XP、Windows 2000和Windows NT 4.0:此属性不可用。由于我的笔记本电脑在此处,因此AdapterTypeID不可靠,WMI将其返回为非无线电。 - ScottN
3个回答

7
您可以在命名空间'root\StandardCimv2'中使用新的WMI类MSFT_NetAdapter。该类是在Windows 8中引入的。
我们可以使用属性ConnectorPresent仅筛选物理适配器。 接下来,我们必须消除Wi-Fi适配器(它存在于物理适配器中),我们可以使用InterfaceType和/或NdisPhysicalMedium属性。 InterfaceType由互联网分配名称机构(IANA)定义,对于所有类似以太网的接口,其值为ethernetCsmacd (6)(请参见https://www.iana.org/assignments/ianaiftype-mib/ianaiftype-mib)。
NdisPhysicalMedium中,以太网适配器的值为0802.3 (14)
因此,我的C#解决方案如下:
try
{
    var objectSearcher = new ManagementObjectSearcher("root\\StandardCimv2", $@"select Name, InterfaceName, InterfaceType, NdisPhysicalMedium from MSFT_NetAdapter where ConnectorPresent=1"); //Physical adapter

    int count = 0;
    foreach (var managementObject in objectSearcher.Get())
    {
        //The locally unique identifier for the network interface. in InterfaceType_NetluidIndex format. Ex: Ethernet_2.
        string interfaceName = managementObject["InterfaceName"]?.ToString();
        //The interface type as defined by the Internet Assigned Names Authority (IANA).
        //https://www.iana.org/assignments/ianaiftype-mib/ianaiftype-mib
        UInt32 interfaceType = Convert.ToUInt32(managementObject["InterfaceType"]);
        //The types of physical media that the network adapter supports.
        UInt32 ndisPhysicalMedium = Convert.ToUInt32(managementObject["NdisPhysicalMedium"]);

        if (!string.IsNullOrEmpty(interfaceName) &&
            interfaceType == 6 &&       //ethernetCsmacd(6) --for all ethernet-like interfaces, regardless of speed, as per RFC3635
            (ndisPhysicalMedium == 0 || ndisPhysicalMedium == 14))   //802.3
        {
            count++;
        }
    }

    return count;
}
catch (ManagementException)
{
    //Run-time requirements WMI MSFT_NetAdapter class is included in Windows 8 and Windows Server 2012
}

这很好。谢谢你。可惜我们仍然在所有设备上使用Windows 7嵌入式系统 :( - ScottN
@HolaJan,我们能否将上面的代码移植到C++中(除了C#构造)?我的意思是想知道是否有另一个C++库/DLL可以实例化相同的管理对象实例和对象搜索机制。 - ultimate cause

4
我看到这是一个老问题,但我在互联网上找到了其他地方的答案,其中描述了如何完成此操作(向下滚动到评论部分)。
评论者的技术允许识别WiFi和蓝牙接口,而所有其他类型可能会被归为一组。如果目标只是将WiFi与以太网适配器区分开来,则应该足够。
查询如下(Powershell示例):
$nics = Get-WmiObject -Namespace "root/CIMV2" -Query "SELECT * FROM Win32_NetworkAdapter"
$types = Get-WmiObject -Namespace "root/WMI" -Query "SELECT * FROM MSNdis_PhysicalMediumType"

第一个查询是常用的方法,它将提供适配器列表。如前所述,可以通过其他选择标准进行过滤,以仅包括有效的物理设备。
第二个查询返回一个带有“NdisPhysicalMediumType”属性的WMI对象,根据链接网站,WiFi的值为9,蓝牙为10,以太网和大多数其他适配器类型为0。
看起来必须在脚本中手动连接这两个查询,使用第一个查询的“Name”或“Description”属性和第二个查询的“InstanceName”属性。

Technet链接已经失效,这是更新后的链接:https://devblogs.microsoft.com/scripting/weekend-scripter-use-powershell-to-identify-network-adapter-characteristics/同时备用的网络存档链接为:https://web.archive.org/web/20220419011251/https://devblogs.microsoft.com/scripting/weekend-scripter-use-powershell-to-identify-network-adapter-characteristics/ - drojf

0
select * from Win32_NetworkAdapter where NetConnectionID LIKE "%Wireless%" or NetConnectionID LIKE "%Wi-Fi%"

2
字符串搜索根本不够可靠。 - seagull

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接