在C#中获取机器MAC地址的可靠方法

我需要一种方法来获取计算机的MAC地址,而不pipe它使用C#运行的操作系统。 应用程序将需要在XP / Vista / Win7 32和64位以及在这些操作系统,但与外语默认。 许多C#命令和操作系统查询不能跨操作系统。 有任何想法吗? 我一直在抓取“ipconfig / all”的输出,但这是非常不可靠的,因为输出格式在每台机器上都不相同。

谢谢

更清洁的解决scheme

var macAddr = ( from nic in NetworkInterface.GetAllNetworkInterfaces() where nic.OperationalStatus == OperationalStatus.Up select nic.GetPhysicalAddress().ToString() ).FirstOrDefault(); 

这是一些C#代码,它返回第一个可用networking接口的MAC地址。 假设NetworkInterface程序集是在其他操作系统上使用的运行时(即Mono)中实现的,那么这可以在其他操作系统上运行。

新版本:以最快的速度返回也具有有效MAC地址的网卡。

 /// <summary> /// Finds the MAC address of the NIC with maximum speed. /// </summary> /// <returns>The MAC address.</returns> private string GetMacAddress() { const int MIN_MAC_ADDR_LENGTH = 12; string macAddress = string.Empty; long maxSpeed = -1; foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces()) { log.Debug( "Found MAC Address: " + nic.GetPhysicalAddress() + " Type: " + nic.NetworkInterfaceType); string tempMac = nic.GetPhysicalAddress().ToString(); if (nic.Speed > maxSpeed && !string.IsNullOrEmpty(tempMac) && tempMac.Length >= MIN_MAC_ADDR_LENGTH) { log.Debug("New Max Speed = " + nic.Speed + ", MAC: " + tempMac); maxSpeed = nic.Speed; macAddress = tempMac; } } return macAddress; } 

原始版本:只返回第一个。

 /// <summary> /// Finds the MAC address of the first operation NIC found. /// </summary> /// <returns>The MAC address.</returns> private string GetMacAddress() { string macAddresses = string.Empty; foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces()) { if (nic.OperationalStatus == OperationalStatus.Up) { macAddresses += nic.GetPhysicalAddress().ToString(); break; } } return macAddresses; } 

我不喜欢这种方法的唯一的事情是,如果你喜欢北电数据包微型端口或某种types的VPN连接,它有可能被选中。 据我所知,没有办法区分实际物理设备的MAC与某种types的虚拟networking接口。

Win32_NetworkAdapterConfiguration WMI类的MACAddress属性可以为您提供一个适配器的MAC地址。 (System.Management命名空间)

 MACAddress Data type: string Access type: Read-only Media Access Control (MAC) address of the network adapter. A MAC address is assigned by the manufacturer to uniquely identify the network adapter. Example: "00:80:C7:8F:6C:96" 

如果您不熟悉WMI API(Windowspipe理规范),则可以在这里了解.NET应用程序。

使用.Net运行时,Windows的所有版本都可以使用WMI。

这是一个代码示例:

 System.Management.ManagementClass mc = default(System.Management.ManagementClass); ManagementObject mo = default(ManagementObject); mc = new ManagementClass("Win32_NetworkAdapterConfiguration"); ManagementObjectCollection moc = mc.GetInstances(); foreach (var mo in moc) { if (mo.Item("IPEnabled") == true) { Adapter.Items.Add("MAC " + mo.Item("MacAddress").ToString()); } } 

如果您连接的计算机是Windows计算机,WMI是最好的解决scheme,但是如果您正在查看Linux,Mac或其他types的networking适配器,那么您将需要使用别的东西。 这里有一些选项:

  1. 使用DOS命令nbtstat -a。 创build一个进程,调用这个命令,parsing输出。
  2. 首先对IP进行Ping操作,确保您的网卡在其ARP表中caching命令,然后使用DOS命令arp -a。 parsing过程的输出,如选项1。
  3. 在iphlpapi.dll中使用可怕的非托pipe调用sendarp

下面是一个项目#3的样本。 如果WMI不是一个可行的解决scheme,这似乎是最好的select:

 using System.Runtime.InteropServices; ... [DllImport("iphlpapi.dll", ExactSpelling = true)] public static extern int SendARP(int DestIP, int SrcIP, byte[] pMacAddr, ref uint PhyAddrLen); ... private string GetMacUsingARP(string IPAddr) { IPAddress IP = IPAddress.Parse(IPAddr); byte[] macAddr = new byte[6]; uint macAddrLen = (uint)macAddr.Length; if (SendARP((int)IP.Address, 0, macAddr, ref macAddrLen) != 0) throw new Exception("ARP command failed"); string[] str = new string[(int)macAddrLen]; for (int i = 0; i < macAddrLen; i++) str[i] = macAddr[i].ToString("x2"); return string.Join(":", str); } 

为了给出信用,这是该代码的基础: http : //www.pinvoke.net/default.aspx/iphlpapi.sendarp#

我们使用WMI来获取具有最低度量的接口的MAC地址,例如,接口窗口将喜欢使用,如下所示:

 public static string GetMACAddress() { ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT * FROM Win32_NetworkAdapterConfiguration where IPEnabled=true"); IEnumerable<ManagementObject> objects = searcher.Get().Cast<ManagementObject>(); string mac = (from o in objects orderby o["IPConnectionMetric"] select o["MACAddress"].ToString()).FirstOrDefault(); return mac; } 

或者在Silverlight中(需要提升信任度):

 public static string GetMACAddress() { string mac = null; if ((Application.Current.IsRunningOutOfBrowser) && (Application.Current.HasElevatedPermissions) && (AutomationFactory.IsAvailable)) { dynamic sWbemLocator = AutomationFactory.CreateObject("WbemScripting.SWBemLocator"); dynamic sWbemServices = sWbemLocator.ConnectServer("."); sWbemServices.Security_.ImpersonationLevel = 3; //impersonate string query = "SELECT * FROM Win32_NetworkAdapterConfiguration where IPEnabled=true"; dynamic results = sWbemServices.ExecQuery(query); int mtu = int.MaxValue; foreach (dynamic result in results) { if (result.IPConnectionMetric < mtu) { mtu = result.IPConnectionMetric; mac = result.MACAddress; } } } return mac; } 

你可以去网卡ID:

  foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces()) { if (nic.OperationalStatus == OperationalStatus.Up){ if (nic.Id == "yay!") } } 

这不是MAC地址,但它是一个唯一的标识符,如果这就是你想要的。

 public static PhysicalAddress GetMacAddress() { var myInterfaceAddress = NetworkInterface.GetAllNetworkInterfaces() .Where(n => n.OperationalStatus == OperationalStatus.Up && n.NetworkInterfaceType != NetworkInterfaceType.Loopback) .OrderByDescending(n => n.NetworkInterfaceType == NetworkInterfaceType.Ethernet) .Select(n => n.GetPhysicalAddress()) .FirstOrDefault(); return myInterfaceAddress; } 

我需要获得用于连接到互联网的实际NIC的MAC; 以确定哪个接口是WCF在我的客户端应用程序中使用。

我看到很多答案,但没有任何帮助我。 希望这个答案有助于某人。

此解决scheme返回正用于连接到互联网的NIC的MAC。

 private static PhysicalAddress GetCurrentMAC(string allowedURL) { TcpClient client = new TcpClient(); client.Client.Connect(new IPEndPoint(Dns.GetHostAddresses(allowedURL)[0], 80)); while(!client.Connected) { Thread.Sleep(500); } IPAddress address2 = ((IPEndPoint)client.Client.LocalEndPoint).Address; client.Client.Disconnect(false); NetworkInterface[] allNetworkInterfaces = NetworkInterface.GetAllNetworkInterfaces(); client.Close(); if(allNetworkInterfaces.Length > 0) { foreach(NetworkInterface interface2 in allNetworkInterfaces) { UnicastIPAddressInformationCollection unicastAddresses = interface2.GetIPProperties().UnicastAddresses; if((unicastAddresses != null) && (unicastAddresses.Count > 0)) { for(int i = 0; i < unicastAddresses.Count; i++) if(unicastAddresses[i].Address.Equals(address2)) return interface2.GetPhysicalAddress(); } } } return null; } 

要调用它,你需要传递一个URL来连接,像这样:

 PhysicalAddress mac = GetCurrentMAC("www.google.com"); 

我真的很喜欢AVee的IP连接度量最低的解决scheme! 但是,如果安装了第二个具有相同指标的网卡,则MAC比较可能会失败。

更好地存储与MAC的接口的描述。 在稍后的比较中,您可以通过此string来识别正确的网页。 这是一个示例代码:

  public static string GetMacAndDescription() { ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT * FROM Win32_NetworkAdapterConfiguration where IPEnabled=true"); IEnumerable<ManagementObject> objects = searcher.Get().Cast<ManagementObject>(); string mac = (from o in objects orderby o["IPConnectionMetric"] select o["MACAddress"].ToString()).FirstOrDefault(); string description = (from o in objects orderby o["IPConnectionMetric"] select o["Description"].ToString()).FirstOrDefault(); return mac + ";" + description; } public static string GetMacByDescription( string description) { ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT * FROM Win32_NetworkAdapterConfiguration where IPEnabled=true"); IEnumerable<ManagementObject> objects = searcher.Get().Cast<ManagementObject>(); string mac = (from o in objects where o["Description"].ToString() == description select o["MACAddress"].ToString()).FirstOrDefault(); return mac; } 

比方说,我有一个TcpConnection使用我的本地IP为192.168.0.182。 然后,如果我想知道该网卡的MAC地址,我将调用meothod: GetMacAddressUsedByIp("192.168.0.182")

 public static string GetMacAddressUsedByIp(string ipAddress) { var ips = new List<string>(); string output; try { // Start the child process. Process p = new Process(); // Redirect the output stream of the child process. p.StartInfo.UseShellExecute = false; p.StartInfo.RedirectStandardOutput = true; p.StartInfo.UseShellExecute = false; p.StartInfo.CreateNoWindow = true; p.StartInfo.FileName = "ipconfig"; p.StartInfo.Arguments = "/all"; p.Start(); // Do not wait for the child process to exit before // reading to the end of its redirected stream. // p.WaitForExit(); // Read the output stream first and then wait. output = p.StandardOutput.ReadToEnd(); p.WaitForExit(); } catch { return null; } // pattern to get all connections var pattern = @"(?xis) (?<Header> (\r|\n) [^\r]+ : \r\n\r\n ) (?<content> .+? (?= ( (\r\n\r\n)|($)) ) )"; List<Match> matches = new List<Match>(); foreach (Match m in Regex.Matches(output, pattern)) matches.Add(m); var connection = matches.Select(m => new { containsIp = m.Value.Contains(ipAddress), containsPhysicalAddress = Regex.Match(m.Value, @"(?ix)Physical \s Address").Success, content = m.Value }).Where(x => x.containsIp && x.containsPhysicalAddress) .Select(m => Regex.Match(m.content, @"(?ix) Physical \s address [^:]+ : \s* (?<Mac>[^\s]+)").Groups["Mac"].Value).FirstOrDefault(); return connection; } 

真的很讨厌挖掘这个旧post,但我觉得这个问题值得Windows 8-10特有的另一个答案。

使用Windows.Networking.Connectivity命名空间中的NetworkInformation ,可以获取正在使用的networking适配器的Id。 然后你可以从前面提到的GetAllNetworkInterfaces()中获得接口MAC地址。

这在Windows Store应用程序中不起作用,因为System.Net中的NetworkInterfaceNetNetInformation不公开GetAllNetworkInterfaces。

 string GetMacAddress() { var connectionProfile = NetworkInformation.GetInternetConnectionProfile(); if (connectionProfile == null) return ""; var inUseId = connectionProfile.NetworkAdapter.NetworkAdapterId.ToString("B").ToUpperInvariant(); if(string.IsNullOrWhiteSpace(inUseId)) return ""; var mac = NetworkInterface.GetAllNetworkInterfaces() .Where(n => inUseId == n.Id) .Select(n => n.GetPhysicalAddress().GetAddressBytes().Select(b=>b.ToString("X2"))) .Select(macBytes => string.Join(" ", macBytes)) .FirstOrDefault(); return mac; } 

ipconfig.exe是使用包括iphlpapi.dll在内的各种DLL实现的…使用iphlpapi.dllsearch,可以iphlpapi MSDN中logging的相应的Win32 API。

尝试这个:

  /// <summary> /// returns the first MAC address from where is executed /// </summary> /// <param name="flagUpOnly">if sets returns only the nic on Up status</param> /// <returns></returns> public static string[] getOperationalMacAddresses(Boolean flagUpOnly) { string[] macAddresses = new string[NetworkInterface.GetAllNetworkInterfaces().Count()]; int i = 0; foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces()) { if (nic.OperationalStatus == OperationalStatus.Up || !flagUpOnly) { macAddresses[i] += ByteToHex(nic.GetPhysicalAddress().GetAddressBytes()); //break; i++; } } return macAddresses; }