it-swarm.com.de

Zuverlässige Methode zum Abrufen der MAC-Adresse der Maschine in C #

Ich brauche einen Weg, um die MAC-Adresse einer Maschine zu erhalten, unabhängig davon, welches Betriebssystem mit C # ausgeführt wird. Die Anwendung muss unter XP/Vista/Win7 32 und 64 Bit sowie unter diesen Betriebssystemen funktionieren, jedoch mit einem fremdsprachlichen Standard. Viele der C # -Befehle und Betriebssystemabfragen funktionieren nicht für alle Betriebssysteme. Irgendwelche Ideen? Ich habe die Ausgabe von "ipconfig/all" abgeschabt, aber das ist unheimlich unzuverlässig, da sich das Ausgabeformat auf jeder Maschine unterscheidet.

Vielen Dank

109
Chase

Sauberere Lösung

var macAddr = 
    (
        from nic in NetworkInterface.GetAllNetworkInterfaces()
        where nic.OperationalStatus == OperationalStatus.Up
        select nic.GetPhysicalAddress().ToString()
    ).FirstOrDefault();

Oder:

String firstMacAddress = NetworkInterface
    .GetAllNetworkInterfaces()
    .Where( nic => nic.OperationalStatus == OperationalStatus.Up && nic.NetworkInterfaceType != NetworkInterfaceType.Loopback )
    .Select( nic => nic.GetPhysicalAddress().ToString() )
    .FirstOrDefault();
109

Hier ist ein C # -Code, der die MAC-Adresse der ersten betriebsbereiten Netzwerkschnittstelle zurückgibt. Angenommen, die Variable NetworkInterface ist in der Laufzeit implementiert (d. H. Mono), die auf anderen Betriebssystemen verwendet wird, dann würde dies auf anderen Betriebssystemen funktionieren.

Neue Version: Liefert die NIC mit der höchsten Geschwindigkeit, die auch eine gültige MAC-Adresse hat.

/// <summary>
/// Finds the MAC address of the NIC with maximum speed.
/// </summary>
/// <returns>The MAC address.</returns>
private string GetMacAddress()
{
    const int MIN_MAC_ADDR_LENGTH = 12;
    string macAddress = string.Empty;
    long maxSpeed = -1;

    foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces())
    {
        log.Debug(
            "Found MAC Address: " + nic.GetPhysicalAddress() +
            " Type: " + nic.NetworkInterfaceType);

        string tempMac = nic.GetPhysicalAddress().ToString();
        if (nic.Speed > maxSpeed &&
            !string.IsNullOrEmpty(tempMac) &&
            tempMac.Length >= MIN_MAC_ADDR_LENGTH)
        {
            log.Debug("New Max Speed = " + nic.Speed + ", MAC: " + tempMac);
            maxSpeed = nic.Speed;
            macAddress = tempMac;
        }
    }

    return macAddress;
}

Originalversion: gibt nur die erste zurück.

/// <summary>
/// Finds the MAC address of the first operation NIC found.
/// </summary>
/// <returns>The MAC address.</returns>
private string GetMacAddress()
{
    string macAddresses = string.Empty;

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

    return macAddresses;
}

Das einzige, was mir an diesem Ansatz nicht gefällt, ist, wenn Sie wie ein Nortel Packet Miniport oder eine Art VPN-Verbindung das Potenzial haben, gewählt zu werden. Soweit ich das beurteilen kann, gibt es keine Möglichkeit, den MAC eines physischen Geräts von einer Art virtueller Netzwerkschnittstelle zu unterscheiden. 

76
blak3r

WMI ist die beste Lösung, wenn der Computer, zu dem Sie eine Verbindung herstellen, ein Windows-Computer ist. Wenn Sie sich jedoch mit einem Linux-, Mac- oder anderen Netzwerkadapter befassen, müssen Sie etwas anderes verwenden. Hier sind einige Optionen:

  1. Verwenden Sie den DOS-Befehl nbtstat -a. Erstellen Sie einen Prozess, rufen Sie diesen Befehl auf, parsen Sie die Ausgabe.
  2. Pingen Sie zunächst die IP-Adresse an, um sicherzustellen, dass Ihre NIC den Befehl in der ARP-Tabelle speichert, und verwenden Sie dann den DOS-Befehl arp -a. Analysieren Sie die Ausgabe des Prozesses wie in Option 1.
  3. Verwenden Sie einen gefürchteten, nicht verwalteten Aufruf, um sendarp in der iphlpapi.dll zu senden

Hier ist ein Exemplar von Punkt 3. Dies scheint die beste Option zu sein, wenn WMI keine praktikable Lösung ist:

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

Um das Guthaben dort zu erteilen, wo es fällig ist, ist dies die Grundlage für diesen Code: http://www.pinvoke.net/default.aspx/iphlpapi.sendarp#

10
Brian Duncan

Die MACAddress - Eigenschaft der Win32_NetworkAdapterConfiguration-WMI-Klasse kann Ihnen die MAC-Adresse eines Adapters liefern. (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"

Wenn Sie mit der WMI-API (Windows Management Instrumentation) nicht vertraut sind, gibt es für .NET-Apps ein gute Übersicht hier .

WMI ist in allen Windows-Versionen mit der .NET-Laufzeitumgebung verfügbar.

Hier ist ein Codebeispiel:

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

Wir verwenden WMI, um die MAC-Adresse der Schnittstelle mit der niedrigsten Metrik abzurufen, z. Die Benutzeroberflächenfenster bevorzugen die Verwendung wie folgt:

public static string GetMACAddress()
{
    ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT * FROM Win32_NetworkAdapterConfiguration where IPEnabled=true");
    IEnumerable<ManagementObject> objects = searcher.Get().Cast<ManagementObject>();
    string mac = (from o in objects orderby o["IPConnectionMetric"] select o["MACAddress"].ToString()).FirstOrDefault();
    return mac;
}

Oder in Silverlight (braucht hohes Vertrauen):

public static string GetMACAddress()
{
    string mac = null;
    if ((Application.Current.IsRunningOutOfBrowser) && (Application.Current.HasElevatedPermissions) && (AutomationFactory.IsAvailable))
    {
        dynamic sWbemLocator = AutomationFactory.CreateObject("WbemScripting.SWBemLocator");
        dynamic sWbemServices = sWbemLocator.ConnectServer(".");
        sWbemServices.Security_.ImpersonationLevel = 3; //impersonate

        string query = "SELECT * FROM Win32_NetworkAdapterConfiguration where IPEnabled=true";
        dynamic results = sWbemServices.ExecQuery(query);

        int mtu = int.MaxValue;
        foreach (dynamic result in results)
        {
            if (result.IPConnectionMetric < mtu)
            {
                mtu = result.IPConnectionMetric;
                mac = result.MACAddress;
            }
        }
    }
    return mac;
}
7
AVee
public static PhysicalAddress GetMacAddress()
{
    var myInterfaceAddress = NetworkInterface.GetAllNetworkInterfaces()
        .Where(n => n.OperationalStatus == OperationalStatus.Up && n.NetworkInterfaceType != NetworkInterfaceType.Loopback)
        .OrderByDescending(n => n.NetworkInterfaceType == NetworkInterfaceType.Ethernet)
        .Select(n => n.GetPhysicalAddress())
        .FirstOrDefault();

    return myInterfaceAddress;
}
6
Tony

Ich brauchte den MAC für die eigentliche NIC, die für die Verbindung zum Internet verwendet wird. um festzustellen, welche Schnittstelle WCF in meiner Client-App verwendet hat.

Ich sehe hier viele Antworten, aber keine, die mir geholfen hat. Hoffe, diese Antworten helfen jemandem.

Diese Lösung gibt die MAC der NIC zurück, die für die Verbindung zum Internet verwendet wird.

private static PhysicalAddress GetCurrentMAC(string allowedURL)
{
  TcpClient client = new TcpClient();
  client.Client.Connect(new IPEndPoint(Dns.GetHostAddresses(allowedURL)[0], 80));
  while(!client.Connected)
  {
    Thread.Sleep(500);  
  }
  IPAddress address2 = ((IPEndPoint)client.Client.LocalEndPoint).Address;
  client.Client.Disconnect(false);
  NetworkInterface[] allNetworkInterfaces = NetworkInterface.GetAllNetworkInterfaces();
  client.Close();
  if(allNetworkInterfaces.Length > 0)
  {
    foreach(NetworkInterface interface2 in allNetworkInterfaces)
    {
      UnicastIPAddressInformationCollection unicastAddresses = interface2.GetIPProperties().UnicastAddresses;
      if((unicastAddresses != null) && (unicastAddresses.Count > 0))
      {
        for(int i = 0; i < unicastAddresses.Count; i++)
          if(unicastAddresses[i].Address.Equals(address2))
            return interface2.GetPhysicalAddress();
      }
    }
  }
  return null;
}

Um es anzurufen, müssen Sie eine URL angeben, um eine Verbindung herzustellen, die wie folgt aussieht:

PhysicalAddress mac = GetCurrentMAC("www.google.com");
5
Darkonekt

IMHO, die erste MAC-Adresse zurückzugeben, ist keine gute Idee, insbesondere wenn virtuelle Maschinen gehostet werden. Daher überprüfe ich die Summe der gesendeten/empfangenen Bytes und wähle die am häufigsten verwendete Verbindung aus, die nicht perfekt ist, aber 9/10 mal korrekt sein sollte.

public string GetDefaultMacAddress()
{
    Dictionary<string, long> macAddresses = new Dictionary<string, long>();
    foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces())
    {
        if (nic.OperationalStatus == OperationalStatus.Up)
            macAddresses[nic.GetPhysicalAddress().ToString()] = nic.GetIPStatistics().BytesSent + nic.GetIPStatistics().BytesReceived;
    }
    long maxValue = 0;
    string mac = "";
    foreach(KeyValuePair<string, long> pair in macAddresses)
    {
        if (pair.Value > maxValue)
        {
            mac = pair.Key;
            maxValue = pair.Value;
        }
    }
    return mac;
}
4
Ramunas

Sie könnten für die NIC ID gehen:

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

Es ist nicht die MAC-Adresse, aber es ist eine eindeutige Kennung, wenn Sie danach suchen. 

4
mmr

Ich mag die Lösung von AVee mit der niedrigsten IP-Verbindungsmetrik! Wenn jedoch ein zweites Gerät mit derselben Metrik installiert wird, kann der MAC-Vergleich fehlschlagen ...

Speichern Sie die Beschreibung der Schnittstelle besser mit dem MAC. In späteren Vergleichen können Sie anhand dieser Zeichenfolge die richtige Marke identifizieren. Hier ist ein Beispielcode:

   public static string GetMacAndDescription()
    {
        ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT * FROM Win32_NetworkAdapterConfiguration where IPEnabled=true");
        IEnumerable<ManagementObject> objects = searcher.Get().Cast<ManagementObject>();
        string mac = (from o in objects orderby o["IPConnectionMetric"] select o["MACAddress"].ToString()).FirstOrDefault();
        string description = (from o in objects orderby o["IPConnectionMetric"] select o["Description"].ToString()).FirstOrDefault();
        return mac + ";" + description;
    }

    public static string GetMacByDescription( string description)
    {
        ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT * FROM Win32_NetworkAdapterConfiguration where IPEnabled=true");
        IEnumerable<ManagementObject> objects = searcher.Get().Cast<ManagementObject>();
        string mac = (from o in objects where o["Description"].ToString() == description select o["MACAddress"].ToString()).FirstOrDefault();
        return mac;
    }
2
Detlef

Ich hasse es wirklich, diesen alten Beitrag zu finden, aber ich denke, die Frage verdient eine andere Antwort, die speziell auf Windows 8-10 zutrifft. 

Mit NetworkInformation aus dem Namespace Windows.Networking.Connectivity können Sie die ID des Netzwerkadapters erhalten, der von Windows verwendet wird. Dann können Sie die Schnittstellen-MAC-Adresse von den zuvor genannten GetAllNetworkInterfaces () erhalten.

Dies funktioniert nicht in Windows Store-Apps, da NetworkInterface in System.Net.NetworkInformation GetAllNetworkInterfaces nicht verfügbar macht.

string GetMacAddress()
{
    var connectionProfile = NetworkInformation.GetInternetConnectionProfile();
    if (connectionProfile == null) return "";

    var inUseId = connectionProfile.NetworkAdapter.NetworkAdapterId.ToString("B").ToUpperInvariant();
    if(string.IsNullOrWhiteSpace(inUseId)) return "";

    var mac = NetworkInterface.GetAllNetworkInterfaces()
        .Where(n => inUseId == n.Id)
        .Select(n => n.GetPhysicalAddress().GetAddressBytes().Select(b=>b.ToString("X2")))
        .Select(macBytes => string.Join(" ", macBytes))
        .FirstOrDefault();

    return mac;
}
2
Greg Gorman

nehmen wir an, ich habe eine TcpConnection mit meiner lokalen IP-Adresse 192.168.0.182. Wenn ich dann die MAC-Adresse dieser NIC wissen möchte, nenne ich das meothod als: GetMacAddressUsedByIp("192.168.0.182")

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;
    }
2
Tono Nam
string mac = "";
foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces())
            {

                if (nic.OperationalStatus == OperationalStatus.Up && (!nic.Description.Contains("Virtual") && !nic.Description.Contains("Pseudo")))
                {
                    if (nic.GetPhysicalAddress().ToString() != "")
                    {
                        mac = nic.GetPhysicalAddress().ToString();
                    }
                }
            }
MessageBox.Show(mac);
1
hadi safari

Blak3r seinen Code ein wenig geändert. Falls Sie zwei Adapter mit der gleichen Geschwindigkeit haben. Nach MAC sortieren, damit Sie immer den gleichen Wert erhalten.

public string GetMacAddress()
{
    const int MIN_MAC_ADDR_LENGTH = 12;
    string macAddress = string.Empty;
    Dictionary<string, long> macPlusSpeed = new Dictionary<string, long>();
    try
    {
        foreach(NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces())
        {
            System.Diagnostics.Debug.WriteLine("Found MAC Address: " + nic.GetPhysicalAddress() + " Type: " + nic.NetworkInterfaceType);

            string tempMac = nic.GetPhysicalAddress().ToString();

            if(!string.IsNullOrEmpty(tempMac) && tempMac.Length >= MIN_MAC_ADDR_LENGTH)
                macPlusSpeed.Add(tempMac, nic.Speed);
        }

        macAddress = macPlusSpeed.OrderByDescending(row => row.Value).ThenBy(row => row.Key).FirstOrDefault().Key;
    }
    catch{}

    System.Diagnostics.Debug.WriteLine("Fastest MAC address: " + macAddress);

    return macAddress;
}
0
user369122

ipconfig.exe wird unter Verwendung verschiedener DLLs implementiert, einschließlich iphlpapi.dll ... Durch Googeln für iphlpapi wird eine entsprechende Win32-API angezeigt, die in MSDN dokumentiert ist.

0
ChrisW

Versuche dies: 

    /// <summary>
    /// returns the first MAC address from where is executed 
    /// </summary>
    /// <param name="flagUpOnly">if sets returns only the nic on Up status</param>
    /// <returns></returns>
    public static string[] getOperationalMacAddresses(Boolean flagUpOnly)
    {
        string[] macAddresses = new string[NetworkInterface.GetAllNetworkInterfaces().Count()];

        int i = 0;
        foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces())
        {
            if (nic.OperationalStatus == OperationalStatus.Up || !flagUpOnly)
            {
                macAddresses[i] += ByteToHex(nic.GetPhysicalAddress().GetAddressBytes());
                //break;
                i++;
            }
        }
        return macAddresses;
    }
0
Richard