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

C# 修改網卡 MAC 地址與 IP 位址:登錄表與 WMI 實作

     編輯:關於C語言

架構概覽

本文示範兩種層級的網路設定修改:

  1. 登錄表層級:永久修改網卡 MAC 地址 (NetworkAddress)、IP 設定 (Tcpip\Parameters\Interfaces)
  2. WMI 層級:動態套用 IP/子網遮罩/閘道/DNS,即時生效無需重啟

⚠️ 警告:修改登錄表需管理員權限,錯誤可能導致網路失效,請先備份登錄表並具備恢復能力。

核心命名空間

using Microsoft.Win32;           // 登錄表操作
using System.Management;           // WMI 查詢與設定 (需參考 System.Management.dll)
using System.Net.NetworkInformation; // 取得網卡資訊
using System.ServiceProcess;       // 重啟網路服務 (可選)

1. 列舉網卡並取得關鍵資訊


public class NetworkAdapterInfo {
    public string Name { get; set; }           // 如 "本地連接"
    public string Description { get; set; }    // 如 "Realtek PCIe GBE Family Controller"
    public string MacAddress { get; set; }     // 物理 MAC
    public string AdapterId { get; set; }      // GUID,對應登錄表子鍵名
    public string IpAddress { get; set; }
    public string SubnetMask { get; set; }
}

public static List GetAdapters() {
    var list = new List();
    foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces()) {
        if (nic.OperationalStatus != OperationalStatus.Up) continue; // 可選:只抓啟用的
        var ipProps = nic.GetIPProperties();
        string ip = "", mask = "";
        foreach (var ua in ipProps.UnicastAddresses) {
            if (ua.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork) {
                ip = ua.Address.ToString();
                mask = ua.IPv4Mask.ToString();
                break;
            }
        }
        list.Add(new NetworkAdapterInfo {
            Name = nic.Name,
            Description = nic.Description,
            MacAddress = nic.GetPhysicalAddress().ToString(),
            AdapterId = nic.Id, // 格式: {GUID}
            IpAddress = ip,
            SubnetMask = mask
        });
    }
    return list;
}

2. 修改 MAC 地址 (登錄表)


// 登錄表路徑: HKLM\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318}\{0000,0001...}
private const string NetClassKeyPath = @"SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318}";

public static bool SetMacAddress(string adapterId, string newMac) {
    // newMac 格式: 12 碼十六進位,不含分隔符,如 "001122334455"
    if (!Regex.IsMatch(newMac, @"^[0-9A-Fa-f]{12}$")) throw new ArgumentException("MAC 格式錯誤");

    using (RegistryKey classKey = Registry.LocalMachine.OpenSubKey(NetClassKeyPath, true)) {
        if (classKey == null) return false;

        foreach (string subKeyName in classKey.GetSubKeyNames()) {
            using (RegistryKey adapterKey = classKey.OpenSubKey(subKeyName, true)) {
                if (adapterKey == null) continue;
                
                // 比對 NetCfgInstanceId 確認是目標網卡
                object val = adapterKey.GetValue("NetCfgInstanceId");
                if (val != null && val.ToString().Equals(adapterId, StringComparison.OrdinalIgnoreCase)) {
                    // 寫入 NetworkAddress (註冊表值型別為 String)
                    adapterKey.SetValue("NetworkAddress", newMac);
                    
                    // 部分驅動程式需同時寫入 Ndi\params\NetworkAddress
                    using (RegistryKey ndiParams = adapterKey.OpenSubKey(@"Ndi\params\NetworkAddress", true)) {
                        if (ndiParams != null) {
                            ndiParams.SetValue("Default", newMac);
                            ndiParams.SetValue("ParamDesc", "Network Address");
                        }
                    }
                    return true;
                }
            }
        }
    }
    return false;
}

3. 修改靜態 IP (登錄表 + WMI 套用)


// 登錄表 IP 路徑: HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\{GUID}
public static bool SetStaticIpRegistry(string adapterId, string ip, string subnet) {
    string tcpipPath = $@"SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\{adapterId}";
    using (RegistryKey key = Registry.LocalMachine.OpenSubKey(tcpipPath, true)) {
        if (key == null) return false;
        key.SetValue("IPAddress", new string[] { ip }, RegistryValueKind.MultiString);
        key.SetValue("SubnetMask", new string[] { subnet }, RegistryValueKind.MultiString);
        // 可選: DefaultGateway, NameServer (DNS)
        return true;
    }
}

// WMI 即時套用 (不需重啟)
public static bool ApplyStaticIpWmi(string adapterId, string ip, string subnet, string gateway = null, string dns = null) {
    try {
        ManagementClass mc = new ManagementClass("Win32_NetworkAdapterConfiguration");
        ManagementObjectCollection moc = mc.GetInstances();
        foreach (ManagementObject mo in moc) {
            if (!(bool)mo["IPEnabled"]) continue;
            if (mo["SettingID"].ToString().Equals(adapterId, StringComparison.OrdinalIgnoreCase)) {
                ManagementBaseObject inParams = mo.GetMethodParameters("EnableStatic");
                inParams["IPAddress"] = new string[] { ip };
                inParams["SubnetMask"] = new string[] { subnet };
                ManagementBaseObject outParams = mo.InvokeMethod("EnableStatic", inParams, null);
                uint ret = (uint)outParams["ReturnValue"];
                if (ret != 0) return false; // 0=成功

                if (!string.IsNullOrEmpty(gateway)) {
                    inParams = mo.GetMethodParameters("SetGateways");
                    inParams["DefaultIPGateway"] = new string[] { gateway };
                    inParams["GatewayCostMetric"] = new int[] { 1 };
                    mo.InvokeMethod("SetGateways", inParams, null);
                }
                if (!string.IsNullOrEmpty(dns)) {
                    inParams = mo.GetMethodParameters("SetDNSServerSearchOrder");
                    inParams["DNSServerSearchOrder"] = new string[] { dns };
                    mo.InvokeMethod("SetDNSServerSearchOrder", inParams, null);
                }
                return true;
            }
        }
    } catch (Exception ex) {
        // 記錄日誌
    }
    return false;
}

4. 重啟網卡使登錄表生效


public static void RestartAdapter(string adapterName) {
    // 方法 1: WMI Disable/Enable
    ManagementClass mc = new ManagementClass("Win32_NetworkAdapter");
    foreach (ManagementObject mo in mc.GetInstances()) {
        if (mo["NetConnectionID"].ToString() == adapterName) {
            mo.InvokeMethod("Disable", null);
            System.Threading.Thread.Sleep(2000);
            mo.InvokeMethod("Enable", null);
            break;
        }
    }

    // 方法 2: 重啟網路服務 (影響所有網卡)
    // using (ServiceController sc = new ServiceController("Tcpip")) { sc.Stop(); sc.Start(); }
}

完整 UI 流程建議

  1. 載入介面時呼叫 GetAdapters() 填入下拉選單
  2. 使用者選擇網卡 → 顯示目前 MAC/IP
  3. 輸入新 MAC (12 碼 Hex) / 新 IP / 子網遮罩 / 閘道 / DNS
  4. 點擊「套用」→ 呼叫 SetMacAddress → SetStaticIpRegistry → ApplyStaticIpWmi → RestartAdapter
  5. 驗證結果:再次呼叫 GetAdapters() 比對

常見問題

問題說明
MAC 修改後不生效部分網卡驅動不支援 NetworkAddress 覆寫;需確認驅動版本或至裝置管理員手動設定
登錄表 IP 修改需重啟登錄表僅為持久化設定,WMI EnableStatic 才能即時生效;建議兩者皆執行
權限不足需以管理員身分執行 (app.manifest 加入 requireAdministrator)
WMI 查詢慢首次查詢較慢,可快取 ManagementObjectSearcher 結果
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved