Get a machines MAC address on the local network from its IP in C#

让人想犯罪 __ 提交于 2019-11-27 01:58:47

问题


I am trying write a function that takes a single IP address as a parameter and queries that machine on my local network for it's MAC address.

I have seen many examples that get the local machine's own MAC address, however none (I've found) that seem to query a local network machine for it.

I know such a task is achievable as this Wake on LAN scanner software scans the local IP range and returns MAC address/Hostname of all on machines.

Can anyone tell me where I'd get started trying to write a function to achieve this in C#? Any help would be appreciated. Thanks

EDIT:

As per Marco Mp's comment below, have used ARP tables. arp class


回答1:


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";
    }
}

Very late edit: In open souce project iSpy (https://github.com/ispysoftware/iSpy) they use this code, which is a little nicer

  public static void RefreshARP()
        {
            _arpList = new Dictionary<string, string>();
            _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

Update 2 even more late, but I think is best because it uses regex that checks better for exact matches.

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<MacIpPair> GetAllMacAddressesAndIppairs()
{
    List<MacIpPair> mip = new List<MacIpPair>();
    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 = @"(?<ip>([0-9]{1,3}\.?){4})\s*(?<mac>([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;
}



回答2:


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) { }

or with PC Name

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));



回答3:


As per Marco Mp's comment above, have used ARP tables. arp class




回答4:


Just a better performing version of the accepted method.

    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<MacIpPair> 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 = @"(?<ip>([0-9]{1,3}\.?){4})\s*(?<mac>([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;
    }


来源:https://stackoverflow.com/questions/12802888/get-a-machines-mac-address-on-the-local-network-from-its-ip-in-c-sharp

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!