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.

8voto

AVee Points 1406

Nous utilisons WMI pour obtenir l'adresse mac de l'interface avec la métrique la plus basse, c'est-à-dire l'interface que Windows préfère utiliser, comme ceci :

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

Ou dans Silverlight (nécessite une confiance élevée) :

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

8voto

Darkonekt Points 89

Cette méthode permet de déterminer l'adresse MAC de l'interface réseau utilisée pour se connecter à l'url et au port spécifiés.

Toutes les réponses données ici ne permettent pas d'atteindre cet objectif.

J'ai écrit cette réponse il y a des années (en 2014). J'ai donc décidé de lui donner un petit "lifting". Veuillez consulter la section des mises à jour.

    /// <summary>
    /// Get the MAC of the Netowrk Interface used to connect to the specified url.
    /// </summary>
    /// <param name="allowedURL">URL to connect to.</param>
    /// <param name="port">The port to use. Default is 80.</param>
    /// <returns></returns>
    private static PhysicalAddress GetCurrentMAC(string allowedURL, int port = 80)
    {
        //create tcp client
        var client = new TcpClient();

        //start connection
        client.Client.Connect(new IPEndPoint(Dns.GetHostAddresses(allowedURL)[0], port));

        //wai while connection is established
        while(!client.Connected)
        {
            Thread.Sleep(500);
        }

        //get the ip address from the connected endpoint
        var ipAddress = ((IPEndPoint)client.Client.LocalEndPoint).Address;

        //if the ip is ipv4 mapped to ipv6 then convert to ipv4
        if(ipAddress.IsIPv4MappedToIPv6)
            ipAddress = ipAddress.MapToIPv4();        

        Debug.WriteLine(ipAddress);

        //disconnect the client and free the socket
        client.Client.Disconnect(false);

        //this will dispose the client and close the connection if needed
        client.Close();

        var allNetworkInterfaces = NetworkInterface.GetAllNetworkInterfaces();

        //return early if no network interfaces found
        if(!(allNetworkInterfaces?.Length > 0))
            return null;

        foreach(var networkInterface in allNetworkInterfaces)
        {
            //get the unicast address of the network interface
            var unicastAddresses = networkInterface.GetIPProperties().UnicastAddresses;

            //skip if no unicast address found
            if(!(unicastAddresses?.Count > 0))
                continue;

            //compare the unicast addresses to see 
            //if any match the ip address used to connect over the network
            for(var i = 0; i < unicastAddresses.Count; i++)
            {
                var unicastAddress = unicastAddresses[i];

                //this is unlikely but if it is null just skip
                if(unicastAddress.Address == null)
                    continue;

                var ipAddressToCompare = unicastAddress.Address;

                Debug.WriteLine(ipAddressToCompare);

                //if the ip is ipv4 mapped to ipv6 then convert to ipv4
                if(ipAddressToCompare.IsIPv4MappedToIPv6)
                    ipAddressToCompare = ipAddressToCompare.MapToIPv4();

                Debug.WriteLine(ipAddressToCompare);

                //skip if the ip does not match
                if(!ipAddressToCompare.Equals(ipAddress))
                    continue;

                //return the mac address if the ip matches
                return networkInterface.GetPhysicalAddress();
            }

        }

        //not found so return null
        return null;
    }

Pour l'appeler, vous devez passer une URL à laquelle vous connecter comme ceci :

var mac = GetCurrentMAC("www.google.com");

Vous pouvez également spécifier un numéro de port. S'il n'est pas spécifié, la valeur par défaut est 80.

MISES À JOUR :

2020

  • Ajout de commentaires pour expliquer le code.
  • Corrigé pour être utilisé avec les plus récentes systèmes d'exploitation plus récents qui utilisent IPV4 mappé à IPV6 (comme Windows 10).
  • Réduction de la nidification.
  • Mise à jour de l'utilisation du code "var".

7voto

Tony Points 2319
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;
}

5voto

mmr Points 7094

Vous pourriez chercher l'identifiant NIC :

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

Ce n'est pas l'adresse MAC, mais c'est un identifiant unique, si c'est ce que vous recherchez.

2voto

Detlef Points 21

J'aime beaucoup la solution d'AVee avec la métrique de connexion IP la plus basse ! Mais si un deuxième nic avec la même métrique est installé, la comparaison MAC peut échouer...

Il est préférable d'enregistrer la description de l'interface avec le MAC. Dans les comparaisons ultérieures, vous pourrez identifier le bon numéro de téléphone grâce à cette chaîne. Voici un exemple de code :

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

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