tags:

views:

4498

answers:

6

I need a way to get a machine's MAC address regardless of the OS it is running using C#. Application will need to work on XP/Vista/Win7 32 and 64 bit as well as on those OSs but with a foreign language default. Many of the C# commands and OS queries don't work across OS. Any ideas? I have been scraping the output of "ipconfig /all" but this is terribly unreliable as the output format differs on every machine.

Thanks

A: 

What do you mean:

Many of the C# commands and OS queries don't work across OS

C# is a programming language. It doesn't have commands.

Also, have you considered the possibility of computers which have # no network adapters, or more than one? What about computers some of whose "network adapters" do not have a MAC address? I seem to recall back in the day that a point to point connection over PPP did not have a MAC address.

John Saunders
Great. Will the downvoter kindly help me understand what I said that he or she didn't like? It's hard to improve without knowing what I did "wrong".
John Saunders
I'm not the down-voter but, at a guess, it may be because you seem to be telling the OP that it's a bad and/or difficult and/or poorly worded question, instead of answering it.
ChrisW
In order to answer a question, it's sometimes necessary to know what the OP meant. Since C# does not have "commands", I thought he likely meant something else. I cannot answer his real question, since I don't yet know what it is. I then proceeded to make sure he knew # MAC Address is not necessarily == 1. Many people don't seem to realize this.
John Saunders
That's what comments are for.
Tamás Szelei
Sorry, what is what comments are for?
John Saunders
+3  A: 

The MACAddress property of the Win32_NetworkAdapterConfiguration WMI class can provide you with an adapter's MAC address. (System.Management Namespace)

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"

If you're not familiar with the WMI API (Windows Management Instrumentation), there's a good overview here for .NET apps.

WMI is available across all version of windows with the .Net runtime.

Here's a code example:

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());
         }
     }
Bayard Randel
A: 

You could go for the NIC ID:

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

It's not the MAC address, but it is a unique identifier, if that's what you're looking for.

mmr
+1  A: 

ipconfig.exe is implemented using various DLLs including iphlpapi.dll ... Googling for iphlpapi reveals a corresponding Win32 API documented in MSDN.

ChrisW
+1  A: 

WMI is the best solution if the machine you are connecting to is a windows machine, but if you are looking at a linux, mac, or other type of network adapter, then you will need to use something else. Here are some options:

  1. Use the DOS command nbtstat -a . Create a process, call this command, parse the output.
  2. First Ping the IP to make sure your NIC caches the command in it's ARP table, then use the DOS command arp -a . Parse the output of the process like in option 1.
  3. Use a dreaded unmanaged call to sendarp in the iphlpapi.dll

Heres a sample of item #3. This seems to be the best option if WMI isn't a viable solution:

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

To give credit where it is due, this is the basis for that code: http://www.pinvoke.net/default.aspx/iphlpapi.sendarp#

Brian Duncan
I was looking for the same thing as the OP and this is the exact thing I needed!
JustSmith
+8  A: 

Here's some C# code which returns the MAC Address of the first operational network interface. Assuming the NetworkInterface assembly is implemented in the runtime (ie Mono) used on other Operating Systems then this would work on other Operating Systems.

    /// <summary>
    /// returns the mac address of the first operation nic found.
    /// </summary>
    /// <returns></returns>
    private string GetMacAddress()
    {
        string macAddresses = "";

        foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces())
        {
            if (nic.OperationalStatus == OperationalStatus.Up)
            {
                macAddresses += nic.GetPhysicalAddress().ToString();
                break;
            }
        }
        return macAddresses;
    }

The only thing I don't like about this approach is if you have like a Nortel Packet Miniport or some type of VPN connection it has the potential of being chosen. As far as I can tell, there is no way to distinguish an actual physical device's MAC from some type of virtual network interface.

blak3r