153 votes

Méthode fiable pour obtenir l'adresse MAC d'une machine en C#

Je dois trouver un moyen d'obtenir l'adresse MAC d'une machine, quel que soit le système d'exploitation qu'elle utilise, en utilisant C#.

L'application devra fonctionner sur XP/Vista/Win7 32bit et 64bit, ainsi que sur ces OS mais avec une langue étrangère par défaut. En outre, de nombreuses commandes C# et requêtes OS ne fonctionnent pas sur tous les OS.

Avez-vous des idées ?

J'ai récupéré la sortie de ipconfig /all mais cela n'est pas du tout fiable car le format de sortie diffère d'une machine à l'autre.

157voto

Mohammed A. Fadil Points 3583

Solution plus propre

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

Ou :

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

83voto

blak3r Points 5096

Voici un code C# qui renvoie l'adresse MAC de la première interface réseau opérationnelle. En supposant que le NetworkInterface est mis en œuvre dans le moteur d'exécution (c'est-à-dire Mono) utilisé sur d'autres systèmes d'exploitation, alors cela fonctionnera sur d'autres systèmes d'exploitation.

Nouvelle version : renvoie la NIC avec la vitesse la plus rapide qui a aussi une adresse MAC valide.

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

Version originale : renvoie simplement la première.

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

La seule chose que je n'aime pas dans cette approche, c'est que si vous disposez d'un miniport Nortel Packet ou d'un type de connexion VPN, vous risquez d'être choisi. Pour autant que je sache, il n'y a aucun moyen de distinguer le MAC d'un périphérique physique réel d'un type d'interface réseau virtuelle.

11voto

Bayard Randel Points 5771

El MACAddress de l Classe WMI Win32_NetworkAdapterConfiguration peut vous fournir l'adresse MAC d'un adaptateur. (Espace de nom System.Management)

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"

Si vous n'êtes pas familier avec l'API WMI (Windows Management Instrumentation), il existe une bon aperçu ici pour les applications .NET.

WMI est disponible dans toutes les versions de Windows avec le moteur d'exécution .Net.

Voici un exemple de code :

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

10voto

Brian Duncan Points 242

WMI est la meilleure solution si la machine à laquelle vous vous connectez est une machine Windows, mais si vous êtes face à un linux, un mac, ou un autre type d'adaptateur réseau, alors vous devrez utiliser autre chose. Voici quelques options :

  1. Utilisez la commande DOS nbtstat -a . Créez un processus, appelez cette commande et analysez la sortie.
  2. Faites d'abord un ping de l'IP pour vous assurer que votre carte réseau cache la commande dans sa table ARP, puis utilisez la commande DOS arp -a . Analysez la sortie du processus comme dans l'option 1.
  3. Utiliser un redoutable appel non géré à sendarp dans le fichier iphlpapi.dll.

Voici un exemple de l'article 3. Cela semble être la meilleure option si WMI n'est pas une solution viable :

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

Pour rendre à César ce qui appartient à César, voici la base de ce code : http://www.pinvoke.net/default.aspx/iphlpapi.sendarp#

10voto

Ramunas Points 36

Je pense que renvoyer la première adresse mac n'est pas une bonne idée, surtout lorsque des machines virtuelles sont hébergées. Je vérifie donc la somme des octets envoyés/reçus et je sélectionne la connexion la plus utilisée, ce n'est pas parfait, mais cela devrait être correct 9/10 fois.

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X