1

I have 4 Ethernet interfaces in my computer (getting the information by ipconfig /all)

For example:
1) IP: 192.168.15.161, MAC: 00-E2-4C-98-18-89
2) IP: 172.168.11.126, MAC: 00-FF-4C-98-18-44
3) IP: 10.0.13.136, MAC: 00-EE-89-98-13-44
4) IP: 195.22.18.146, MAC: 00-12-89-98-13-33

I need a function that returns the MAC address when given IP.

For example getMacByIP("192.168.15.161") will return "00-E2-4C-98-18-89"

Using arp is not working for local!

For example arp -a will not give the local address with MAC
So all the questions/answers like here are not helping me.

I've searched a lot over the internet before asking this question.

EDIT:

This answer: (link) not helping me

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

Because if I'm using, for example, Chinese version of Windows, the Regex will not work!

cheziHoyzer
  • 4,803
  • 12
  • 54
  • 81
  • 1
    Possible duplicate of [Reliable method to get machine's MAC address in C#](https://stackoverflow.com/questions/850650/reliable-method-to-get-machines-mac-address-in-c-sharp) – Svek May 28 '17 at 10:11
  • No!! it's not correct! all the answer there are not solving my problem. they return the first/active. I want specific MAC by IP. one answer give this function but it's not good answer! because if I got windows not in English it will not work!! – cheziHoyzer May 28 '17 at 10:31
  • You're not reading all the answers, or trying to understand the complexities with this kind of problem. There are a lot of other things to consider such as the number of assigned addresses to an interface, and the type of address you are trying to match, etc. – Svek May 28 '17 at 10:40
  • I've read all the answer one by one and tested it!! non of them is good solution for me!! please remove the duplicate – cheziHoyzer May 28 '17 at 10:53
  • I just updated my answer to match up with your question – Svek May 28 '17 at 11:01
  • I'll check it, Thank you!! – cheziHoyzer May 28 '17 at 11:08
  • Working! Thanks for your elegant solution! – cheziHoyzer May 28 '17 at 11:10

1 Answers1

2

Here is a proposed solution that does what you are asking for:

void Main()
{
    Console.WriteLine(GetMacByIP("192.168.15.161")); // will return "00-E2-4C-98-18-89"
}

public string GetMacByIP(string ipAddress)
{
    // grab all online interfaces
    var query = NetworkInterface.GetAllNetworkInterfaces()
        .Where(n =>
            n.OperationalStatus == OperationalStatus.Up && // only grabbing what's online
            n.NetworkInterfaceType != NetworkInterfaceType.Loopback)
        .Select(_ => new
        {
            PhysicalAddress = _.GetPhysicalAddress(),
            IPProperties = _.GetIPProperties(),
        });

    // grab the first interface that has a unicast address that matches your search string
    var mac = query
        .Where(q => q.IPProperties.UnicastAddresses
            .Any(ua => ua.Address.ToString() == ipAddress))
        .FirstOrDefault()
        .PhysicalAddress;

    // return the mac address with formatting (eg "00-00-00-00-00-00")
    return String.Join("-", mac.GetAddressBytes().Select(b => b.ToString("X2")));
}
Svek
  • 12,350
  • 6
  • 38
  • 69
  • Why did you use q.IPProperties.UnicastAddresses? Why do you need interface that has a unicast address? – cheziHoyzer May 28 '17 at 11:25
  • @cheziHoyzer - This is what I was trying to warn you about earlier. It's not always going to be simple. You have `Anycast`, `Unicast`, `Multicast`, for more info... https://msdn.microsoft.com/en-us/library/system.net.networkinformation.ipinterfaceproperties(v=vs.110).aspx – Svek May 28 '17 at 11:28