首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C# 取得本機 MAC、IP、主機名稱完整範例

     編輯:關於C語言

概述

在授權驗證、裝置識別、網路診斷等場景需取得本機網路資訊。本文提供跨平台相容的實作,涵蓋 IPv4/IPv6、多網卡、實體/虛擬介面過濾。

核心代碼


using System;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Management; // 需參考 System.Management.dll

public static class NetworkInfo
{
    public static NetworkIdentity GetLocalIdentity()
    {
        return new NetworkIdentity
        {
            HostName = Dns.GetHostName(),
            IpAddresses = GetIpAddresses(),
            MacAddresses = GetMacAddresses()
        };
    }

    // 取得所有非回環 IPv4/IPv6 位址
    public static IPAddress[] GetIpAddresses()
    {
        return Dns.GetHostEntry(Dns.GetHostName())
            .AddressList
            .Where(ip => ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork ||
                         ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6)
            .Where(ip => !IPAddress.IsLoopback(ip))
            .ToArray();
    }

    // 取得實體網卡 MAC 位址(排除虛擬介面、隧道、回環)
    public static PhysicalAddress[] GetMacAddresses()
    {
        return NetworkInterface.GetAllNetworkInterfaces()
            .Where(nic => nic.OperationalStatus == OperationalStatus.Up)
            .Where(nic => nic.NetworkInterfaceType != NetworkInterfaceType.Loopback)
            .Where(nic => nic.NetworkInterfaceType != NetworkInterfaceType.Tunnel)
            .Where(nic => !nic.Description.Contains("Virtual", StringComparison.OrdinalIgnoreCase))
            .Where(nic => !nic.Description.Contains("Hyper-V", StringComparison.OrdinalIgnoreCase))
            .Where(nic => nic.GetPhysicalAddress().Length > 0)
            .Select(nic => nic.GetPhysicalAddress())
            .Distinct()
            .ToArray();
    }

    // 使用 WMI 取得啟用 IP 的網卡 MAC(舊版相容)
    public static string GetMacByWmi()
    {
        try
        {
            using (var mc = new ManagementClass("Win32_NetworkAdapterConfiguration"))
            using (var moc = mc.GetInstances())
            {
                foreach (ManagementObject mo in moc)
                {
                    if (mo["IPEnabled"]?.ToString() == "True")
                    {
                        return mo["MacAddress"]?.ToString()?.Replace(":", "-");
                    }
                }
            }
        }
        catch { /* WMI 不可用時靜默失敗 */ }
        return null;
    }
}

public class NetworkIdentity
{
    public string HostName { get; set; }
    public IPAddress[] IpAddresses { get; set; }
    public PhysicalAddress[] MacAddresses { get; set; }

    public string PrimaryIpv4 => IpAddresses?.FirstOrDefault(ip => ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)?.ToString();
    public string PrimaryMac => MacAddresses?.FirstOrDefault()?.ToString();

    public override string ToString()
    {
        return $"Host: {HostName}\nIPv4: {PrimaryIpv4}\nMAC: {PrimaryMac}";
    }
}

使用範例


public class Program
{
    public static void Main()
    {
        var info = NetworkInfo.GetLocalIdentity();
        
        Console.WriteLine("=== 本機網路身分 ===");
        Console.WriteLine($"主機名稱: {info.HostName}");
        Console.WriteLine($"主要 IPv4: {info.PrimaryIpv4 ?? "N/A"}");
        Console.WriteLine($"主要 MAC: {info.PrimaryMac ?? "N/A"}");
        
        Console.WriteLine("\n所有 IP 位址:");
        foreach (var ip in info.IpAddresses)
            Console.WriteLine($"  {ip} ({ip.AddressFamily})");
        
        Console.WriteLine("\n所有 MAC 位址:");
        foreach (var mac in info.MacAddresses)
            Console.WriteLine($"  {mac}");
    }
}

輸出範例


=== 本機網路身分 ===
主機名稱: DESKTOP-ABC123
主要 IPv4: 192.168.1.105
主要 MAC: 00-1A-2B-3C-4D-5E

所有 IP 位址:
  192.168.1.105 (InterNetwork)
  fe80::1a2b:3c4d:5e6f:7890%12 (InterNetworkV6)

所有 MAC 位址:
  00-1A-2B-3C-4D-5E
  00-1A-2B-3C-4D-5F

進階主題

取得特定網卡資訊(含 Gateway、DNS、DHCP)


public static NetworkDetail GetDetail(string macAddress)
{
    var nic = NetworkInterface.GetAllNetworkInterfaces()
        .FirstOrDefault(n => n.GetPhysicalAddress().ToString().Equals(macAddress, StringComparison.OrdinalIgnoreCase));
    
    if (nic == null) return null;

    var ipProps = nic.GetIPProperties();
    var ipv4 = ipProps.UnicastAddresses
        .FirstOrDefault(a => a.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork);

    return new NetworkDetail
    {
        Name = nic.Name,
        Description = nic.Description,
        Mac = nic.GetPhysicalAddress().ToString(),
        IpAddress = ipv4?.Address.ToString(),
        SubnetMask = ipv4?.IPv4Mask.ToString(),
        Gateway = ipProps.GatewayAddresses
            .Where(g => g.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
            .Select(g => g.Address.ToString())
            .FirstOrDefault(),
        DnsServers = ipProps.DnsAddresses
            .Where(d => d.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
            .Select(d => d.ToString())
            .ToArray(),
        IsDhcpEnabled = ipProps.GetIPv4Properties()?.IsDhcpEnabled ?? false
    };
}

跨平台注意事項

平台NetworkInformationSystem.Management (WMI)
Windows✅ 完整支援✅ 完整支援
Linux✅ 核心功能支援❌ 不支援
macOS✅ 核心功能支援❌ 不支援
Docker 容器⚠️ 看宿主機設定❌ 不支援

跨平台專案請優先使用 System.Net.NetworkInformation,WMI 僅作為 Windows 專用補充。

授權綁定最佳實踐


public static string GenerateDeviceFingerprint()
{
    var info = NetworkInfo.GetLocalIdentity();
    var mac = info.PrimaryMac ?? "NO-MAC";
    var hostname = info.HostName ?? "NO-HOST";
    
    // 結合多因子產生指紋,避免單一 MAC 變更導致授權失效
    string raw = $"{hostname}|{mac}|{Environment.MachineName}|{Environment.ProcessorCount}";
    using (var sha = System.Security.Cryptography.SHA256.Create())
    {
        byte[] hash = sha.ComputeHash(System.Text.Encoding.UTF8.GetBytes(raw));
        return Convert.ToBase64String(hash)[..24]; // 取前 24 字元
    }
}

常見問題

  • MAC 為空:檢查網卡是否啟用、驅動程式、虛擬機網路模式(NAT/Bridged)
  • 多張網卡不確定哪張是「主要」:優先選擇有 Gateway、非虛擬、OperationalStatus=Up 的介面
  • Docker 容器取得宿主機 MAC:需採用 Host 網路模式或透過 API 查詢宿主
  • 權限不足:WMI 需管理員權限,NetworkInformation 通常不需

總結

使用 NetworkInterface.GetAllNetworkInterfaces() 為現代跨平台首選,搭配 LINQ 過濾虛擬介面。授權綁定建議採用多因子指紋而非單一 MAC,提高彈性與安全性。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved