Monday, May 11, 2009

Get MAC Address in C# from IP Address/Hostname

Stumble del.icio.us Reddit MyWeb! Facebook Google bookmark

I was hoping to find something to get MAC address of a machine given its IP address or hostname. There could be multiple ways to do the same. But I thought I'll give the "nbtstat" a chance. nbtstat is a command in windows which gets you the details about protocol statistics and current TCP/IP connections using NBT (NetBIOS over TCP/IP). Here is a small program in C# which does the exact same thing: (If you want just the exe, let me know via a comment here and I'll send you the executable.)


    1 // No copyrights(c). Use as you wish!

    2 

    3 using System;

    4 using System.Diagnostics;

    5 using System.Net;

    6 using System.Net.NetworkInformation;

    7 using System.Runtime.InteropServices;

    8 using System.Text;

    9 

   10 namespace Yours.Truly

   11 {

   12     // *************************************************************************

   13     /// <summary>

   14     /// A class to get the MAC address from IP address. The same class can be

   15     /// modified a little to get the MAC address from the specified hostname.

   16     /// </summary>

   17     public class GetMacAddressFromIPAddress

   18     {

   19         /// <summary> Ping timeout (in ms) </summary>

   20         private const int PING_TIMEOUT = 1000;

   21 

   22         // *********************************************************************

   23         /// <summary>

   24         /// Initializes a new instance of <see cref="GetMacAddressFromIPAddress"/>.

   25         /// </summary>

   26         public GetMacAddressFromIPAddress()

   27         {

   28         }

   29 

   30         // *********************************************************************

   31         /// <summary>

   32         /// Gets the MAC address from specified <paramref name="IPAddress"/>

   33         /// using nbtstat in hyphen (-) separated format.

   34         /// </summary>

   35         /// <remarks>

   36         /// <para>

   37         /// The same class can be modified to accept hostname and then resolve

   38         /// the hostname to Ip address to get the MAC address or just pass "-a"

   39         /// argument to "nbtstat" to get the mac address from hostname. If you

   40         /// want to find the MAC address from only the IP address change the

   41         /// switch to "-A".

   42         /// </para>

   43         /// <para>

   44         /// The current program can resolve both hostname as well as IP address

   45         /// to MAC address. The "-a" argument can actually accept both IP address

   46         /// as well as hostname.

   47         /// </para>

   48         /// </remarks>

   49         /// <param name="ipAddress">The IP address or hostname for the machine

   50         /// for which the MAC address is desired.</param>

   51         /// <returns>A string containing the MAC address if MAC address could be

   52         /// found.An empty or null string otherwise.</returns>

   53         private string GetMacAddress(string ipAddress)

   54         {

   55             string macAddress = string.Empty;

   56 

   57             if (!IsHostAccessible(ipAddress)) return null;

   58             try

   59             {

   60                 ProcessStartInfo processStartInfo = new ProcessStartInfo();

   61                 Process process = new Process();

   62                 processStartInfo.FileName = "nbtstat";

   63                 processStartInfo.RedirectStandardInput = false;

   64                 processStartInfo.RedirectStandardOutput = true;

   65                 processStartInfo.Arguments = "-a " + ipAddress;

   66                 processStartInfo.UseShellExecute = false;

   67                 process = Process.Start(processStartInfo);

   68 

   69                 int Counter = -1;

   70 

   71                 while (Counter <= -1)

   72                 {

   73                     // Look for the words "mac address" in the output.

   74                     // The output usually looks likes this:

   75 

   76                     // Local Area Connection:

   77                     //Node IpAddress: [13.15.111.222] Scope Id: []

   78 

   79                     //           NetBIOS Remote Machine Name Table

   80 

   81                     //       Name               Type        Status

   82                     //    --------------------------------------------

   83                     //    SAMGLS0790W    <00>  UNIQUE      Registered

   84                     //    SAMPLS0790W    <20>  UNIQUE      Registered

   85                     //    NA            <00>  GROUP       Registered

   86 

   87                     //    MAC Address = 00-21-70-2B-A5-43

   88 

   89                     Counter =

   90                         macAddress.Trim().ToLower().IndexOf("mac address", 0);

   91                     if (Counter > -1)

   92                     {

   93                         break;

   94                     }

   95                     macAddress = process.StandardOutput.ReadLine();

   96                 }

   97                 process.WaitForExit();

   98                 macAddress = macAddress.Trim();

   99             }

  100             catch (Exception e)

  101             {

  102                 // Something unexpected happened? Inform the user

  103                 // The possibilities are:

  104                 // 1.That the machine is not on the network currently

  105                 // 2. The IP address/hostname supplied are not on the same network

  106                 // 3. The host was not found on the same subnet or could not be

  107                 //    resolved

  108                 Console.WriteLine("Failed because:" + e.ToString());

  109             }

  110 

  111             return macAddress;

  112         }

  113 

  114         #region Getting MAC from ARP

  115 

  116         [DllImport("iphlpapi.dll", ExactSpelling = true)]

  117         static extern int SendARP(int DestIP, int SrcIP, byte[] pMacAddr,

  118             ref uint PhyAddrLen);

  119 

  120         // *********************************************************************

  121         /// <summary>

  122         /// Gets the MAC address from ARP table in colon (:) separated format.

  123         /// </summary>

  124         /// <param name="hostNameOrAddress">Host name or IP address of the

  125         /// remote host for which MAC address is desired.</param>

  126         /// <returns>A string containing MAC address; null if MAC address could

  127         /// not be found.</returns>

  128         private string GetMACAddressFromARP(string hostNameOrAddress)

  129         {

  130             if (!IsHostAccessible(hostNameOrAddress)) return null;

  131 

  132             IPHostEntry hostEntry = Dns.GetHostEntry(hostNameOrAddress);

  133             if (hostEntry.AddressList.Length == 0)

  134                 return null;

  135 

  136             byte[] macAddr = new byte[6];

  137             uint macAddrLen = (uint) macAddr.Length;

  138             if (SendARP((int) hostEntry.AddressList[0].Address, 0, macAddr,

  139                 ref macAddrLen) != 0)

  140                 return null;

  141 

  142             StringBuilder macAddressString = new StringBuilder();

  143             for (int i = 0; i < macAddr.Length; i++)

  144             {

  145                 if (macAddressString.Length > 0)

  146                     macAddressString.Append(":");

  147 

  148                 macAddressString.AppendFormat("{0:x2}", macAddr[i]);

  149             }

  150 

  151             return macAddressString.ToString();

  152         } // end GetMACAddressFromARP

  153 

  154         #endregion Getting MAC from ARP

  155 

  156         // *********************************************************************

  157         /// <summary>

  158         /// Checks to see if the host specified by

  159         /// <paramref name="hostNameOrAddress"/> is currently accessible.

  160         /// </summary>

  161         /// <param name="hostNameOrAddress">Host name or IP address of the

  162         /// remote host for which MAC address is desired.</param>

  163         /// <returns><see langword="true" /> if the host is currently accessible;

  164         /// <see langword="false"/> otherwise.</returns>

  165         private static bool IsHostAccessible(string hostNameOrAddress)

  166         {

  167             Ping ping = new Ping();

  168             PingReply reply = ping.Send(hostNameOrAddress, PING_TIMEOUT);

  169             return reply.Status == IPStatus.Success;

  170         }

  171 

  172         // *********************************************************************

  173         /// <summary>

  174         /// The netry point for the application.

  175         /// </summary>

  176         /// <param name="args">An array of command line arguments.</param>

  177         [STAThread]

  178         static void Main(string[] args)

  179         {

  180             bool macRequired = true;

  181             while (macRequired)

  182             {

  183                 Console.WriteLine("Enter the IP address for which mac address is " +

  184                                 "required:(Enter exit to quit the program.)");

  185                 string ipAddress = Console.ReadLine();

  186                 StringComparer cp = StringComparer.OrdinalIgnoreCase;

  187                 if (cp.Compare(ipAddress, "Exit") == 0) break;

  188 

  189                 GetMacAddressFromIPAddress getMacAddress =

  190                     new GetMacAddressFromIPAddress();

  191 

  192                 Console.WriteLine("Please wait while I try to find the MAC address...");

  193                 // You may also use the ARP table. Call GetMACAddressFromARP here

  194                 string MacAddress = getMacAddress.GetMacAddress(ipAddress);

  195 

  196                 Console.WriteLine(MacAddress);

  197             } // end while

  198         }

  199 

  200     } // end class GetMacAddressFromIPAddress

  201 

  202 } // end namespace Yours.Truly


22 comments:

  1. Very good post...so simple yet exactly what I needed.

    ReplyDelete
  2. Thank you, it is a very interesting post.
    Anyway i wish you used pure C# code for netbios, without using the external OS tool.

    Bye.

    ReplyDelete
  3. I don't know if you have tried this in Windows 7, but it won't work for some reason. I keep getting a Win32Exception more or less telling me that it cannot find nbtstat even though it's in the Path and I know it's there.

    ReplyDelete
    Replies
    1. add this line above line 60:
      string filePath = Environment.GetFolderPath(Environment.SpecialFolder.Windows) + "\\sysnative";

      then modify the call like this:
      62 processStartInfo.FileName = filePath + "\\nbtstat.exe";

      Delete
  4. Hey nice post. Please send me exe file .

    My email :hemanth2208@gmail.com

    ReplyDelete
  5. Please send me this *.exe I need desperately for a project I'm working on where I really want to avoid having to Hostname>IP>Mac if I can go Hostname>Mac will save me days of work. thanks. nerdcub@gmail.com

    ReplyDelete
  6. I want To Implement Of Windows Form

    ReplyDelete
  7. can i get the .exe file please send me

    ReplyDelete
  8. at this email address "naveed_ku83@live.com"

    ReplyDelete
  9. I need this project too... please, send me "forever_14_420@hotmail.com". Thx!

    ReplyDelete
  10. at this email address please send the project "r4redu@yahoo.com"

    ReplyDelete
  11. Please send me at verma_saurab86h@yahoo.com

    ReplyDelete
  12. please send me @ ylulie4.wu.et@gmail.com

    ReplyDelete
  13. Horrid ... using output from a command line to do something like this... what if the output changes with the next release of windows? ... anyway a much better way of doing this is here: http://stackoverflow.com/questions/1148778/how-do-i-access-arp-protocol-information-through-net have a look at the bit where it says: This is an example of the GetIpNetTable

    Kris

    ReplyDelete
  14. Please send me this project and executable file as well to nnwhlaing@hotmail.com. thanks.

    ReplyDelete
  15. Oh My God !
    Such a complex code to find the mac address of network adapter. Not even the technical person would like this complex code.

    Thanks
    Silvester Norman

    Change Mac Address

    ReplyDelete
  16. great job master .. can i have the exe ? please email me easztilloh_o7o1@yahoo.com

    ReplyDelete
  17. I need this project send me on andiruddhasathe@gmail.com

    ReplyDelete
  18. Can i have the exe? please mail me at patel_aipl@outlook.com

    ReplyDelete
  19. thank you u save my day

    ReplyDelete

Please leave your opinion...