Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/302.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/163.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/arduino/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 用于获取本地计算机MAC地址的Win32_NetworkAdapter WMI类的快速替换_C#_C++_Windows_Networking_Wmi - Fatal编程技术网

C# 用于获取本地计算机MAC地址的Win32_NetworkAdapter WMI类的快速替换

C# 用于获取本地计算机MAC地址的Win32_NetworkAdapter WMI类的快速替换,c#,c++,windows,networking,wmi,C#,C++,Windows,Networking,Wmi,TL;此问题的DR版本:WMI类包含我需要的信息,但速度太慢。在Windows上获取MACAddress、ConfigManagerErrorCode和PNPDeviceID列信息的更快方法是什么 我需要检索连接的网络适配器的信息,以便获得唯一标识本地Microsoft Windows计算机的MAC地址。WMI类似乎具有我要查找的信息。MACAddress、ConfigManagerErrorCode和PNPDeviceID列是我真正需要的唯一列: MACAddress:MAC地址(此操作的目

TL;此问题的DR版本:WMI类包含我需要的信息,但速度太慢。在Windows上获取MACAddress、ConfigManagerErrorCode和PNPDeviceID列信息的更快方法是什么

我需要检索连接的网络适配器的信息,以便获得唯一标识本地Microsoft Windows计算机的MAC地址。WMI类似乎具有我要查找的信息。MACAddress、ConfigManagerErrorCode和PNPDeviceID列是我真正需要的唯一列:

  • MACAddress:MAC地址(此操作的目标)
  • ConfigManagerErrorCode:允许我确定适配器是否已启用并正在运行。(如果它被禁用,那么我应该使用我的应用程序以前缓存的MAC地址(如果可用)
  • PNPDeviceID:通过检查前缀“PCI”(如果需要,可能还有其他接口),我可以筛选出非物理适配器,其中有几个在我的Windows 7机箱上(包括虚拟适配器,如VMware/VirtualBox)
我的计划是使用PNPDeviceID过滤掉非物理设备。然后,我将在任何剩余的表条目上使用MACAddress列(将地址保存到缓存)。当设备被禁用(可能由非零ConfigManagerErrorCode指示)且MACAddress为空时,我可以从缓存中为该设备使用以前看到的MACAddress

您可以在我的Windows 7计算机上看到此表的内容。你可以看到里面有很多垃圾,但是只有一个条目带有“PCI”PNPDeviceID

wmic:root\cli>NIC GET Caption, ConfigManagerErrorCode, MACAddress, PNPDeviceID
Caption                                                   ConfigManagerErrorCode  MACAddress         PNPDeviceID
[00000000] WAN Miniport (SSTP)                            0                                          ROOT\MS_SSTPMINIPORT\0000
[00000001] WAN Miniport (IKEv2)                           0                                          ROOT\MS_AGILEVPNMINIPORT\0000
[00000002] WAN Miniport (L2TP)                            0                                          ROOT\MS_L2TPMINIPORT\0000
[00000003] WAN Miniport (PPTP)                            0                                          ROOT\MS_PPTPMINIPORT\0000
[00000004] WAN Miniport (PPPOE)                           0                                          ROOT\MS_PPPOEMINIPORT\0000
[00000005] WAN Miniport (IPv6)                            0                                          ROOT\MS_NDISWANIPV6\0000
[00000006] WAN Miniport (Network Monitor)                 0                                          ROOT\MS_NDISWANBH\0000
[00000007] Intel(R) 82567LM-2 Gigabit Network Connection  0                       00:1C:C0:B0:C4:89  PCI\VEN_8086&DEV_10CC&SUBSYS_00008086&REV_00\3&33FD14CA&0&C8
[00000008] WAN Miniport (IP)                              0                                          ROOT\MS_NDISWANIP\0000
[00000009] Microsoft ISATAP Adapter                       0                                          ROOT\*ISATAP\0000
[00000010] RAS Async Adapter                              0                       20:41:53:59:4E:FF  SW\{EEAB7790-C514-11D1-B42B-00805FC1270E}\ASYNCMAC
[00000011] Microsoft Teredo Tunneling Adapter             0                                          ROOT\*TEREDO\0000
[00000012] VirtualBox Bridged Networking Driver Miniport  0                       00:1C:C0:B0:C4:89  ROOT\SUN_VBOXNETFLTMP\0000
[00000013] VirtualBox Host-Only Ethernet Adapter          0                       08:00:27:00:C4:A1  ROOT\NET\0000
[00000014] Microsoft ISATAP Adapter                       0                                          ROOT\*ISATAP\0001
[00000015] VMware Virtual Ethernet Adapter for VMnet1     0                       00:50:56:C0:00:01  ROOT\VMWARE\0000
[00000016] Microsoft ISATAP Adapter                       0                                          ROOT\*ISATAP\0002
[00000017] VMware Virtual Ethernet Adapter for VMnet8     0                       00:50:56:C0:00:08  ROOT\VMWARE\0001
[00000018] Microsoft ISATAP Adapter                       0                                          ROOT\*ISATAP\0003
(如果禁用物理适配器,则MACAddress列变为null,ConfigManagerErrorCode变为非零)

不幸的是,这个类太慢了。在我相对现代的基于Windows 7 Core i7的计算机上,对Win32_NetworkAdapter的任何查询始终需要0.3秒。因此,使用此选项将使应用程序启动时间再增加0.3秒(或更糟),这是我无法接受的。这尤其是因为我想不出一个合理的理由来解释为什么要花这么长时间才能弄清楚本地计算机上的MAC地址和即插即用设备ID

public static void ShowNetworkInterfaces()
{
    IPGlobalProperties computerProperties = IPGlobalProperties.GetIPGlobalProperties();
    NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces();
    Console.WriteLine("Interface information for {0}.{1}     ",
            computerProperties.HostName, computerProperties.DomainName);
    if (nics == null || nics.Length < 1)
    {
        Console.WriteLine("  No network interfaces found.");
        return;
    }

    Console.WriteLine("  Number of interfaces .................... : {0}", nics.Length);
    foreach (NetworkInterface adapter in nics)
    {
        IPInterfaceProperties properties = adapter.GetIPProperties(); //  .GetIPInterfaceProperties();
        Console.WriteLine();
        Console.WriteLine(adapter.Description);
        Console.WriteLine(String.Empty.PadLeft(adapter.Description.Length,'='));
        Console.WriteLine("  Interface type .......................... : {0}", adapter.NetworkInterfaceType);
        Console.Write("  Physical address ........................ : ");
        PhysicalAddress address = adapter.GetPhysicalAddress();
        byte[] bytes = address.GetAddressBytes();
        for(int i = 0; i< bytes.Length; i++)
        {
            // Display the physical address in hexadecimal.
            Console.Write("{0}", bytes[i].ToString("X2"));
            // Insert a hyphen after each byte, unless we are at the end of the 
            // address.
            if (i != bytes.Length -1)
            {
                 Console.Write("-");
            }
        }
        Console.WriteLine();
    }
}
搜索获取MAC地址的其他方法产生了和更新的函数。他们没有WMI施加的0.3秒惩罚。这些函数是.NET Framework类(通过检查.NET源代码确定)和“ipconfig”命令行工具(通过使用确定)使用的函数

我用C#做了一个简单的例子,列出了使用NetworkInterface类的所有网络适配器。不幸的是,使用这些API似乎有两个缺点:

  • 这些API甚至没有列出禁用的网络适配器。这意味着我无法从缓存中查找禁用适配器的MAC地址
  • 我不知道如何让PNPDeviceID过滤掉非物理适配器
我的问题是:我可以使用什么方法来获取本地计算机物理适配器的MAC地址(无论是否启用),最多只需几十毫秒

<>(我在C和C++都有经验,而且阅读其他语言很好,所以我真的不在乎答案中会用到什么语言)。 编辑:响应Alex K关于仅使用return immediate和forward的建议,并为我正在做的工作提供一些示例WMI代码-下面是一些列出感兴趣列的C#代码:

    public static void NetTest() {
        System.Diagnostics.Stopwatch sw = System.Diagnostics.Stopwatch.StartNew();
        EnumerationOptions opt = new EnumerationOptions();
        // WMI flag suggestions from Alex K:
        opt.ReturnImmediately = true;
        opt.Rewindable = false;
        ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\cimv2", "select MACAddress, PNPDeviceID, ConfigManagerErrorCode from Win32_NetworkAdapter", opt);
        foreach (ManagementObject obj in searcher.Get()) {
            Console.WriteLine("=========================================");
            foreach (PropertyData pd in obj.Properties) {
                Console.WriteLine("{0} = {1}", pd.Name, pd.Value);
            }
        }
        Console.WriteLine(sw.Elapsed.TotalSeconds);
    }
我调用了这个函数3次,每次都在最后一行打印了大约0.36秒。因此,建议的标志似乎没有任何效果:正面或负面。这并不奇怪,因为的答案似乎表明,除非有大量记录(例如数百到数千条),否则不会观察到性能的变化,而Win32_NetworkAdapter表则不是这样

编辑2:建议从IP helper API使用多个答案(这是具有GetAdapterInfo函数的同一个API)。与GetAdapterInfo相比,它在查找本地MAC地址方面有什么优势?我想不出任何信息——表面上看,GetAdapterInfo似乎比SendARP对本地适配器返回的信息更全面。现在回想起来,我认为我的问题的很大一部分集中在枚举的概念上:首先,计算机上存在哪些适配器?SendARP不执行枚举:它假定您已经知道您想要MAC的适配器的IP地址。我需要弄清楚系统上存在哪些适配器。这引发了一些问题:

  • 如果拔下网络电缆,会发生什么情况?这在笔记本电脑上非常常见,例如(未连接的以太网、未连接的WiFi卡)。我尝试使用NetworkInterface.GetAllNetworkInterfaces()并列出媒体拔出时使用的所有单播地址。Windows没有列出地址,所以我想不出任何可以传递给SendARP的地址。直观地说,拔掉插头的适配器仍然有一个物理地址,但没有IP地址(因为它不在具有DHCP服务器的网络上)
  • 这让我想到:我如何获得一个本地IP地址列表,用SendARP进行测试
  • 如何获取每个适配器的PNPDeviceID(或可用于筛选非物理适配器的类似ID)
  • 如何列出禁用的适配器,以便从缓存中查找MAC地址(即上次启用时找到的MAC地址)

SendARP似乎没有解决这些问题,这是我问这个问题的主要原因(否则我将使用GetAdapterInfo并继续处理…。

您应该能够从
System.Net
命名空间获得所需的一切。例如,下面的语句和w