148

C# を使用して、実行中の OS に関係なく、マシンの MAC アドレスを取得する方法が必要です。

アプリケーションは、XP/Vista/Win7 32 ビットおよび 64 ビット、およびこれらの OS で動作する必要がありますが、デフォルトは外国語です。また、C# コマンドと OS クエリの多くは、すべての OS で機能するとは限りません。

あなたはなにか考えはありますか?

の出力をスクレイピングしてきましたipconfig /allが、マシンごとに出力形式が異なるため、これは非常に信頼できません。

4

17 に答える 17

153

クリーナー ソリューション

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

または:

String firstMacAddress = NetworkInterface
    .GetAllNetworkInterfaces()
    .Where( nic => nic.OperationalStatus == OperationalStatus.Up && nic.NetworkInterfaceType != NetworkInterfaceType.Loopback )
    .Select( nic => nic.GetPhysicalAddress().ToString() )
    .FirstOrDefault();
于 2011-10-05T13:12:40.560 に答える
83

最初の動作中のネットワーク インターフェイスの MAC アドレスを返す C# コードを次に示します。アセンブリが他のオペレーティング システムで使用されるランタイム (つまり、Mono) に実装されていると仮定すると、NetworkInterfaceこれは他のオペレーティング システムでも機能します。

新しいバージョン: 有効な MAC アドレスを持つ最速の NIC を返します。

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

元のバージョン: 最初のものだけを返します。

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

このアプローチについて私が気に入らない唯一の点は、Nortel Packet Miniport や何らかのタイプの VPN 接続が選択される可能性がある場合です。私の知る限り、実際の物理デバイスの MAC をある種の仮想ネットワーク インターフェイスと区別する方法はありません。

于 2009-10-13T15:39:48.463 に答える
10

接続先のマシンが Windows マシンの場合は WMI が最適なソリューションですが、Linux、Mac、またはその他のタイプのネットワーク アダプタを検討している場合は、別のものを使用する必要があります。以下にいくつかのオプションを示します。

  1. DOS コマンド nbtstat -a を使用します。プロセスを作成し、このコマンドを呼び出して、出力を解析します。
  2. 最初にIPをpingして、NICがARPテーブルにコマンドをキャッシュしていることを確認してから、DOSコマンド arp -a を使用します。オプション 1 のように、プロセスの出力を解析します。
  3. iphlpapi.dll で sendarp への恐ろしいアンマネージ呼び出しを使用する

アイテム #3 のサンプルを次に示します。WMI が実行可能なソリューションでない場合、これが最適なオプションのようです。

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

当然のことながら、これはそのコードの基礎です: http://www.pinvoke.net/default.aspx/iphlpapi.sendarp#

于 2009-09-11T20:49:08.520 に答える
9

特に仮想マシンがホストされている場合、最初のMACアドレスを返すIMHOはお勧めできません。したがって、送信/受信バイトの合計をチェックし、最も使用されている接続を選択します。これは完璧ではありませんが、9/10 回は正しいはずです。

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;
}
于 2018-08-13T12:02:01.060 に答える
8

このメソッドは、指定された URL とポートへの接続に使用されるネットワーク インターフェイスの MAC アドレスを決定します。

ここでのすべての回答は、この目標を達成することはできません。

私はこの回答を何年も前に(2014年に)書きました。そこで、少し「フェイスリフト」をすることにしました。アップデートセクションを見てください

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

それを呼び出すには、次のように接続する URL を渡す必要があります。

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

ポート番号を指定することもできます。指定しない場合、デフォルトは 80 です。

更新:

2020年

  • コードを説明するコメントを追加しました。
  • IPV6 にマップされた IPV4 を使用する新しいオペレーティング システム (windows 10 など) で使用するように修正されました。
  • ネスティングを減らしました。
  • 「var」を使用するコードをアップグレードしました。
于 2014-10-03T14:46:49.710 に答える
8

WMI を使用して、メトリックが最も低いインターフェイスの MAC アドレスを取得します。たとえば、インターフェイス ウィンドウは次のように使用することを好みます。

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

または Silverlight の場合 (高度な信頼が必要):

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;
}
于 2012-06-21T12:30:45.563 に答える
2

私は、IP 接続メトリックが最も低い AVee のソリューションが本当に気に入っています! しかし、同じメトリックを持つ 2 番目の NIC がインストールされている場合、MAC 比較は失敗する可能性があります...

MAC とのインターフェイスの説明を保存することをお勧めします。後の比較では、この文字列によって正しい nic を識別できます。サンプルコードは次のとおりです。

   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;
    }
于 2012-11-15T15:48:03.700 に答える
2

この古い投稿を掘り下げるのは本当に嫌いですが、Windows 8-10 に固有の別の回答に値する質問だと思います。

Windows.Networking.Connectivity名前空間のNetworkInformationを使用すると、Windowsが使用しているネットワーク アダプターの ID を取得できます。次に、前述の GetAllNetworkInterfaces() からインターフェイスの MAC アドレスを取得できます。

System.Net.NetworkInformation のNetworkInterfaceは GetAllNetworkInterfaces を公開しないため、これは Windows ストア アプリでは機能しません。

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;
}
于 2016-07-04T05:01:00.533 に答える
1

blak3r のコードを少し変更しました。同じ速度のアダプターが 2 つある場合。MAC で並べ替えると、常に同じ値が得られます。

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;
}
于 2017-11-24T13:03:47.677 に答える
0

これを試して:

    /// <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;
    }
于 2014-02-07T20:25:50.387 に答える