Obtenga una dirección MAC de la máquina en la red local desde su IP en C #

Estoy intentando escribir una función que toma una única IP address como parámetro y consulta esa máquina en mi red local para obtener su MAC address .

He visto muchos ejemplos que obtienen la MAC address propia de la máquina local, sin embargo ninguno (he encontrado) que parece consultar a una máquina de la red local.

Sé que esta tarea se puede realizar ya que este software de escáner Wake on LAN escanea el rango de IP local y devuelve la dirección MAC / nombre de host de todas las máquinas.

¿Puede alguien decirme dónde comencé a intentar escribir una función para lograr esto en C #? Cualquier ayuda sería apreciada. Gracias

EDITAR:

Según el comentario de Marco Mp a continuación, se han utilizado tablas ARP. clase arp

 public string GetMacAddress(string ipAddress) { string macAddress = string.Empty; System.Diagnostics.Process pProcess = new System.Diagnostics.Process(); pProcess.StartInfo.FileName = "arp"; pProcess.StartInfo.Arguments = "-a " + ipAddress; pProcess.StartInfo.UseShellExecute = false; pProcess.StartInfo.RedirectStandardOutput = true; pProcess.StartInfo.CreateNoWindow = true; pProcess.Start(); string strOutput = pProcess.StandardOutput.ReadToEnd(); string[] substrings = strOutput.Split('-'); if (substrings.Length >= 8) { macAddress = substrings[3].Substring(Math.Max(0, substrings[3].Length - 2)) + "-" + substrings[4] + "-" + substrings[5] + "-" + substrings[6] + "-" + substrings[7] + "-" + substrings[8].Substring(0, 2); return macAddress; } else { return "not found"; } } 

Edición muy tardía: en el proyecto abierto iSpy ( https://github.com/ispysoftware/iSpy ) usan este código, que es un poco mejor

  public static void RefreshARP() { _arpList = new Dictionary(); _arpList.Clear(); try { var arpStream = ExecuteCommandLine("arp", "-a"); // Consume first three lines for (int i = 0; i < 3; i++) { arpStream.ReadLine(); } // Read entries while (!arpStream.EndOfStream) { var line = arpStream.ReadLine(); if (line != null) { line = line.Trim(); while (line.Contains(" ")) { line = line.Replace(" ", " "); } var parts = line.Trim().Split(' '); if (parts.Length == 3) { string ip = parts[0]; string mac = parts[1]; if (!_arpList.ContainsKey(ip)) _arpList.Add(ip, mac); } } } } catch (Exception ex) { Logger.LogExceptionToFile(ex, "ARP Table"); } if (_arpList.Count > 0) { foreach (var nd in List) { string mac; ARPList.TryGetValue(nd.IPAddress.ToString(), out mac); nd.MAC = mac; } } } 

https://github.com/ispysoftware/iSpy/blob/master/Server/NetworkDeviceList.cs

Actualización 2 aún más tarde, pero creo que es mejor porque usa expresiones regulares que comprueban mejor las coincidencias exactas.

 public string getMacByIp(string ip) { var macIpPairs = GetAllMacAddressesAndIppairs(); int index = macIpPairs.FindIndex(x => x.IpAddress == ip); if (index >= 0) { return macIpPairs[index].MacAddress.ToUpper(); } else { return null; } } public List GetAllMacAddressesAndIppairs() { List mip = new List(); System.Diagnostics.Process pProcess = new System.Diagnostics.Process(); pProcess.StartInfo.FileName = "arp"; pProcess.StartInfo.Arguments = "-a "; pProcess.StartInfo.UseShellExecute = false; pProcess.StartInfo.RedirectStandardOutput = true; pProcess.StartInfo.CreateNoWindow = true; pProcess.Start(); string cmdOutput = pProcess.StandardOutput.ReadToEnd(); string pattern = @"(?([0-9]{1,3}\.?){4})\s*(?([a-f0-9]{2}-?){6})"; foreach (Match m in Regex.Matches(cmdOutput, pattern, RegexOptions.IgnoreCase)) { mip.Add(new MacIpPair() { MacAddress = m.Groups["mac"].Value, IpAddress = m.Groups["ip"].Value }); } return mip; } public struct MacIpPair { public string MacAddress; public string IpAddress; } 
 using System.Net; using System.Runtime.InteropServices; [DllImport("iphlpapi.dll", ExactSpelling = true)] public static extern int SendARP(int DestIP, int SrcIP, [Out] byte[] pMacAddr, ref int PhyAddrLen); try { IPAddress hostIPAddress = IPAddress.Parse("XXX.XXX.XXX.XX"); byte[] ab = new byte[6]; int len = ab.Length, r = SendARP((int)hostIPAddress.Address, 0, ab, ref len); Console.WriteLine(BitConverter.ToString(ab, 0, 6)); } catch (Exception ex) { } 

o con nombre de PC

 try { Tempaddr = System.Net.Dns.GetHostEntry("DESKTOP-xxxxxx"); } catch (Exception ex) { } byte[] ab = new byte[6]; int len = ab.Length, r = SendARP((int)Tempaddr.AddressList[1].Address, 0, ab, ref len); Console.WriteLine(BitConverter.ToString(ab, 0, 6)); 

Según el comentario de Marco Mp anterior, se han utilizado tablas ARP. clase arp

Sólo una versión de mejor rendimiento del método aceptado.

  public string GetMacByIp( string ip ) { var pairs = this.GetMacIpPairs(); foreach( var pair in pairs ) { if( pair.IpAddress == ip ) return pair.MacAddress; } throw new Exception( $"Can't retrieve mac address from ip: {ip}" ); } public IEnumerable GetMacIpPairs() { System.Diagnostics.Process pProcess = new System.Diagnostics.Process(); pProcess.StartInfo.FileName = "arp"; pProcess.StartInfo.Arguments = "-a "; pProcess.StartInfo.UseShellExecute = false; pProcess.StartInfo.RedirectStandardOutput = true; pProcess.StartInfo.CreateNoWindow = true; pProcess.Start(); string cmdOutput = pProcess.StandardOutput.ReadToEnd(); string pattern = @"(?([0-9]{1,3}\.?){4})\s*(?([a-f0-9]{2}-?){6})"; foreach( Match m in Regex.Matches( cmdOutput, pattern, RegexOptions.IgnoreCase ) ) { yield return new MacIpPair() { MacAddress = m.Groups[ "mac" ].Value, IpAddress = m.Groups[ "ip" ].Value }; } } public struct MacIpPair { public string MacAddress; public string IpAddress; }