![](/img/trans.png)
[英]NetAddresses always null in Win32_NetworkAdapter query
[英]Fast replacement for Win32_NetworkAdapter WMI class for getting MAC address of local computer
TL;此問題的DR版本:WMI Win32_NetworkAdapter類包含我需要的信息,但速度太慢。 在Windows上獲取MACAddress,ConfigManagerErrorCode和PNPDeviceID列的信息的更快的方法是什么?
我需要檢索連接的網絡適配器的信息,以便我可以獲得一個MAC地址來唯一標識本地Microsoft Windows計算機。 WMI Win32_NetworkAdapter類似乎有我正在尋找的信息。 MACAddress,ConfigManagerErrorCode和PNPDeviceID列是我真正需要的唯一列:
我的計划是使用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。
搜索獲取MAC地址的其他方法產生了GetAdaptersInfo和較新的GetAdaptersAddresses函數。 他們沒有WMI強加的0.3秒罰款。 這些函數是.NET Framework的NetworkInterface類(通過檢查.NET源代碼確定)和“ipconfig”命令行工具(通過使用Dependency Walker確定)使用的函數。
我在C#中做了一個簡單的例子,列出了使用NetworkInterface類的所有網絡適配器。 不幸的是,使用這些API似乎有兩個缺點:
我的問題是:我可以使用什么方法在幾十毫秒內獲取本地計算機的物理適配器的MAC地址(無論是否啟用)?
(我在C#和C ++都很有經驗,讀完其他語言很好,所以我真的不在乎答案中可能使用的語言)。
編輯:回應Alex K的建議只使用return immediate and 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秒。 所以建議的標志似乎沒有任何影響:正面或負面。 這不是太令人驚訝,作為如何在C#中進行只進,只讀WMI查詢的答案? 似乎表明除非有大量記錄(例如數百到數千),否則不會觀察到性能變化,而Win32_NetworkAdapter表則不然。
編輯2:已經提出了多個答案來使用來自IP幫助程序API的SendARP (這是具有GetAdaptersInfo函數的相同API)。 這有什么優勢可以讓GetAdaptersInfo找到本地MAC地址? 我無法想到 - 從表面上看,GetAdaptersInfo似乎返回比SendARP對本地適配器更完整的信息集。 現在我考慮一下,我認為我的問題的一個重要部分集中在枚舉的概念上:首先在計算機上存在哪些適配器? SendARP不執行枚舉:它假定您已經知道您想要MAC的適配器的IP地址。 我需要弄清楚系統上存在哪些適配器。 這引起了一些問題:
SendARP似乎沒有解決這些問題,這是我提出這個問題的主要原因(否則我會使用GetAdaptersInfo繼續處理......)。
我最終將WMI完全排除在外,並在獲得我想要的信息的同時取得了顯着的進步。 如WMI所述,獲得結果需要> 0.30秒。 使用我的版本,我可以在大約0.01秒內獲得相同的信息。
我使用了安裝API,配置管理器API,然后直接在NDIS網絡驅動程序上發出OID請求以獲取MAC地址。 設置API看起來非常慢,特別是在獲取屬性值等內容時。 必須將設置API調用保持在最低限度。 (通過查看在設備管理器中加載設備的“詳細信息”選項卡所需的時間,您實際上可以看到它有多糟糕)。
猜測為什么WMI這么慢:我注意到無論我查詢哪個屬性子集,WMI的Win32_NetworkAdapter總是花費相同的時間。 看起來像WMI Win32_NetworkAdapter類程序員很懶,並沒有優化他們的類只收集其他WMI類所做的請求信息。 他們可能收集所有信息,無論是否要求。 他們可能非常依賴Setup API來執行此操作,並且對緩慢的Setup API的過度調用以獲取不需要的信息是導致它如此緩慢的原因。
我所做的高級概述:
結果是PC上的MAC地址的強大指示應該不受VMware,VirtualBox制造的“假”網卡的影響,很大程度上不受暫時禁用的網卡的影響,並且不受通過USB,ExpressCard連接的瞬態網卡的影響, PC卡或任何未來的可移動接口。
編輯:所有網卡都不支持IOCTL_NDIS_QUERY_GLOBAL_STATS。 絕大多數工作,但一些英特爾卡沒有。 有關其設備實例ID,請參閱如何可靠,快速地獲取網卡的MAC地址
您應該能夠從System.Net
命名空間獲得所需的一切。 例如,以下示例從MSDN中解除,並在問題的原始版本中執行您要求的操作。 它顯示本地計算機上所有接口的物理地址。
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();
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.