当前位置: 首页 > news >正文

C#编程实现Windows静态IP自动配置:WMI与netsh方案详解

1. 项目概述:为什么我们需要用代码管理网络配置?

在IT运维、自动化部署、设备初始化或者某些特定的客户端应用场景里,手动去控制面板里点来点去设置IP地址,绝对是个效率杀手。想象一下,你要给机房里的几十上百台新上架的服务器配置管理IP,或者为一批工业控制电脑设定固定的生产网络参数,如果全靠人工,不仅耗时费力,还极易出错。这时候,一个能够通过程序自动、准确、批量设置静态IP地址和网关的工具,价值就凸显出来了。

这个用C#实现的项目,正是为了解决这个问题。它绕开了图形界面,直接与Windows系统的网络配置核心——WMI(Windows Management Instrumentation)或更现代的NetShell(netsh)命令进行交互,实现对网络适配器参数的编程式控制。对于开发者,尤其是从事运维工具开发、客户端系统管理软件或物联网(IoT)设备管理的朋友来说,掌握这项技能意味着你能将网络配置能力无缝集成到自己的产品中,提升软件的自动化水平和专业度。

网上能找到的很多代码片段可能只解决了部分问题,或者缺乏健壮的错误处理。本文将带你从零开始,深入原理,构建一个健壮、可复用的C#静态IP设置类库,并附上完整的、可直接编译运行的源码。我们会涵盖从识别网卡、设置IPv4地址、子网掩码、网关,到设置DNS服务器等全套流程,并重点讲解其中的坑和最佳实践。

2. 核心原理与方案选型:WMI vs. netsh

在Windows下,用程序配置网络主要有两条技术路径:通过WMI(Win32_NetworkAdapterConfiguration类)和通过执行netsh命令。我们的项目将主要基于WMI,因为它更“原生”,提供了面向对象的编程接口,能获得更精细的控制和更丰富的状态信息。

2.1 WMI方案深度解析

WMI是微软提供的核心管理框架,可以把它想象成Windows系统的一个超级管理API。我们要用到的Win32_NetworkAdapterConfiguration类,包含了网卡配置的所有属性(IP、网关、DNS等)和方法(启用DHCP、设置静态IP等)。

它的核心优势在于:

  1. 信息全面:可以枚举出所有网络适配器的详细信息,包括描述、MAC地址、IP地址列表等,便于我们精准定位目标网卡。
  2. 操作原子化:调用其方法(如EnableStaticSetGateways)是直接的系统级操作,成功与否有明确的返回值。
  3. 状态同步:通过WMI查询可以立即获取配置变更后的状态。

但缺点也很明显:

  1. 权限要求高:需要管理员权限(UAC)才能执行修改操作。
  2. 复杂度稍高:需要处理COM对象和Management类,代码量比调用命令行要多。
  3. 对某些特殊网卡支持可能不佳:虽然极少见,但一些虚拟网卡或非常旧的驱动可能不完全兼容。

2.2 netsh命令方案作为补充

netsh是Windows自带的强大网络配置命令行工具。通过Process.Start调用netsh interface ip set address ...等命令,同样可以完成设置。

它的优点是:

  1. 简单粗暴:一行命令解决问题,对于快速原型或脚本非常友好。
  2. 历史悠久,极其稳定:是微软官方维护的命令行工具,兼容性极广。

缺点是:

  1. 输出解析麻烦:需要解析命令行输出来判断成功与否,不够优雅。
  2. 信息获取不便:用命令获取当前配置信息,并进行解析,比WMI查询要繁琐得多。
  3. 有被弃用风险:微软在推广新的网络配置模型,但netsh在可预见的未来仍会广泛支持。

我们的选择:本项目将以WMI作为主要实现方式,因为它更适合集成到一个严谨的C#类库中。同时,我们也会在关键部分提及netsh的等效命令,作为备选方案或用于验证。为了健壮性,我们甚至可以在代码中实现一个回退机制:当WMI调用失败时,尝试使用netsh命令。

3. 实战:构建健壮的静态IP设置类库

接下来,我们一步步构建这个类库。我们将创建一个名为NetworkConfigurator的类。

3.1 环境准备与项目创建

首先,打开Visual Studio(2019/2022均可),新建一个“C# 控制台应用”项目,命名为StaticIPSetter。为了使用WMI,我们需要引用System.Management程序集。在解决方案资源管理器中,右键点击项目“引用” -> “添加引用” -> 在“程序集”中搜索并勾选System.Management,然后确定。

注意:.NET Core/.NET 5+ 项目默认不包含此引用,需要手动通过NuGet包管理器安装System.Management包。在包管理器控制台中执行:Install-Package System.Management

3.2 核心类设计与网卡识别

我们的核心类是NetworkConfigurator。首先要解决的是如何找到我们要配置的那块物理网卡。通常我们通过网卡的“描述”或“名称”来识别。

using System.Management; using System.Net.NetworkInformation; public class NetworkConfigurator { // 目标网卡的描述(例如:“Intel(R) Ethernet Connection (7) I219-LM”) public string TargetAdapterDescription { get; set; } public NetworkConfigurator(string adapterDescription) { TargetAdapterDescription = adapterDescription; } // 方法1:使用WMI获取特定网卡的配置对象 private ManagementObject GetNetworkAdapterManagementObject() { string query = $"SELECT * FROM Win32_NetworkAdapterConfiguration WHERE Description = '{TargetAdapterDescription}'"; ManagementObjectSearcher searcher = new ManagementObjectSearcher(query); ManagementObjectCollection collection = searcher.Get(); if (collection.Count == 0) { throw new InvalidOperationException($"未找到描述为 '{TargetAdapterDescription}' 的网络适配器。"); } // 假设描述是唯一的,取第一个 return collection.OfType<ManagementObject>().FirstOrDefault(); } // 方法2:辅助方法,获取所有网卡信息供用户选择 public static List<NetworkInterfaceInfo> GetAllNetworkAdapters() { var adapters = new List<NetworkInterfaceInfo>(); ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT * FROM Win32_NetworkAdapterConfiguration WHERE IPEnabled = TRUE"); foreach (ManagementObject mo in searcher.Get()) { string description = mo["Description"]?.ToString() ?? "Unknown"; string[] ips = (string[]) (mo["IPAddress"] ?? new string[0]); string mac = mo["MACAddress"]?.ToString() ?? "Unknown"; adapters.Add(new NetworkInterfaceInfo { Description = description, IPAddresses = ips, MACAddress = mac, Index = int.Parse(mo["Index"]?.ToString() ?? "0") }); } return adapters; } } public class NetworkInterfaceInfo { public string Description { get; set; } public string[] IPAddresses { get; set; } public string MACAddress { get; set; } public int Index { get; set; } }

实操心得Win32_NetworkAdapterConfigurationIPEnabled = TRUE这个条件非常关键,它过滤掉了那些没有启用TCP/IP协议的适配器(比如蓝牙网络连接、虚拟专用网络适配器等),让我们只看到真正可配置的网卡。获取网卡列表后,最好将描述和当前IP一起显示出来,方便用户确认。

3.3 设置静态IP地址与子网掩码

找到目标网卡的管理对象后,就可以调用EnableStatic方法来设置静态IP。这个方法需要两个参数:IP地址数组和子网掩码数组。通常我们只设置一个IPv4地址。

public bool SetStaticIP(string ipAddress, string subnetMask) { if (string.IsNullOrWhiteSpace(ipAddress) || string.IsNullOrWhiteSpace(subnetMask)) throw new ArgumentException("IP地址和子网掩码不能为空。"); using (ManagementObject mo = GetNetworkAdapterManagementObject()) { if (mo == null) return false; // 准备参数 string[] addresses = { ipAddress }; string[] masks = { subnetMask }; // 调用EnableStatic方法 ManagementBaseObject inParams = mo.GetMethodParameters("EnableStatic"); inParams["IPAddress"] = addresses; inParams["SubnetMask"] = masks; ManagementBaseObject outParams = mo.InvokeMethod("EnableStatic", inParams, null); // 返回值 (uint) 0 表示成功,其他值表示失败 uint returnValue = (uint)outParams["ReturnValue"]; return returnValue == 0; } }

关键点解析

  1. EnableStatic方法用于启用静态IP。对应的,启用DHCP的方法是EnableDHCP
  2. 参数是数组类型,这是为了支持一个网卡绑定多个IP地址(多IP绑定)的场景。我们这里只用一个。
  3. ReturnValue是WMI方法调用的标准返回值。0代表成功。常见的非零错误码如91(参数错误)、84(IP正在使用)等,在生产代码中需要根据这些值给出更友好的错误提示。

3.4 设置默认网关

设置网关使用的是SetGateways方法。这里有个非常重要的细节:网关参数中的“跃点数”(Metric)。跃点数决定了路由的优先级,数值越小优先级越高。如果不指定,系统会使用默认值。

public bool SetGateway(string gateway, int gatewayMetric = 1) { if (string.IsNullOrWhiteSpace(gateway)) throw new ArgumentException("网关地址不能为空。"); using (ManagementObject mo = GetNetworkAdapterManagementObject()) { if (mo == null) return false; // 注意:网关和跃点数都需要是数组,且一一对应。 string[] gateways = { gateway }; string[] metrics = { gatewayMetric.ToString() }; ManagementBaseObject inParams = mo.GetMethodParameters("SetGateways"); inParams["DefaultIPGateway"] = gateways; inParams["GatewayCostMetric"] = metrics; // 注意这里是字符串数组 ManagementBaseObject outParams = mo.InvokeMethod("SetGateways", inParams, null); uint returnValue = (uint)outParams["ReturnValue"]; return returnValue == 0; } }

重要提示GatewayCostMetric参数在WMI接口中预期的是一个字符串数组string[]),而不是整数数组。这是一个非常容易踩坑的地方。如果你传入int[],方法会执行失败。务必像上面代码一样,将跃点数转换为字符串。

3.5 设置DNS服务器

DNS设置相对独立,使用SetDNSServerSearchOrder方法。你可以设置一个首选DNS和一个备用DNS。

public bool SetDnsServers(string primaryDns, string secondaryDns = null) { using (ManagementObject mo = GetNetworkAdapterManagementObject()) { if (mo == null) return false; // 构建DNS服务器数组 List<string> dnsServers = new List<string> { primaryDns }; if (!string.IsNullOrWhiteSpace(secondaryDns)) { dnsServers.Add(secondaryDns); } ManagementBaseObject inParams = mo.GetMethodParameters("SetDNSServerSearchOrder"); // 如果传入null或空数组,则表示启用DHCP自动获取DNS inParams["DNSServerSearchOrder"] = dnsServers.ToArray(); ManagementBaseObject outParams = mo.InvokeMethod("SetDNSServerSearchOrder", inParams, null); uint returnValue = (uint)outParams["ReturnValue"]; return returnValue == 0; } }

注意事项:将DNSServerSearchOrder参数设置为null或空数组,会清除静态DNS设置,并恢复为从DHCP自动获取DNS。这个行为与EnableDHCP方法不同,后者会同时恢复IP和DNS的自动获取。

3.6 完整的配置方法与异常处理

现在,我们将上面的方法组合起来,形成一个完整的配置流程,并加入更完善的异常处理和日志。

public class NetworkConfigurationResult { public bool IsSuccess { get; set; } public string Message { get; set; } public Exception Error { get; set; } } public NetworkConfigurationResult ConfigureStaticIP(string ip, string subnet, string gateway, string primaryDns, string secondaryDns = null) { var result = new NetworkConfigurationResult(); try { // 1. 验证输入(简单的格式验证,生产环境应用更严格的正则) if (!System.Net.IPAddress.TryParse(ip, out _)) throw new ArgumentException("IP地址格式无效。"); if (!System.Net.IPAddress.TryParse(subnet, out _)) throw new ArgumentException("子网掩码格式无效。"); if (!System.Net.IPAddress.TryParse(gateway, out _)) throw new ArgumentException("网关地址格式无效。"); if (!System.Net.IPAddress.TryParse(primaryDns, out _)) throw new ArgumentException("主DNS格式无效。"); if (secondaryDns != null && !System.Net.IPAddress.TryParse(secondaryDns, out _)) throw new ArgumentException("备用DNS格式无效。"); // 2. 设置静态IP和子网掩码 Console.WriteLine($"[INFO] 正在设置IP地址: {ip}/{subnet}..."); if (!SetStaticIP(ip, subnet)) { result.IsSuccess = false; result.Message = "设置静态IP失败。请检查IP/子网掩码是否冲突,或是否有其他程序占用。"; return result; } // 3. 设置网关 Console.WriteLine($"[INFO] 正在设置网关: {gateway}..."); if (!SetGateway(gateway)) { // 网关设置失败,尝试回滚IP?(可选,但需谨慎) // SetDHCP(); // 例如,恢复DHCP result.IsSuccess = false; result.Message = "设置网关失败。网关地址可能不在同一网段。"; return result; } // 4. 设置DNS Console.WriteLine($"[INFO] 正在设置DNS服务器: {primaryDns}, {secondaryDns ?? "无"}..."); if (!SetDnsServers(primaryDns, secondaryDns)) { result.IsSuccess = false; result.Message = "设置DNS服务器失败。"; return result; } // 5. 可选:立即刷新DNS缓存,使新DNS生效 RefreshDnsCache(); result.IsSuccess = true; result.Message = $"网络配置成功!IP: {ip}, 网关: {gateway}, DNS: {primaryDns}"; Console.WriteLine($"[SUCCESS] {result.Message}"); } catch (ArgumentException ex) { result.IsSuccess = false; result.Message = $"参数错误: {ex.Message}"; result.Error = ex; } catch (InvalidOperationException ex) { result.IsSuccess = false; result.Message = $"操作失败: {ex.Message}"; result.Error = ex; } catch (ManagementException ex) { result.IsSuccess = false; result.Message = $"WMI管理错误: {ex.Message}"; result.Error = ex; } catch (Exception ex) { result.IsSuccess = false; result.Message = $"发生未预期的错误: {ex.Message}"; result.Error = ex; } return result; } private void RefreshDnsCache() { // 调用 ipconfig /flushdns 命令刷新DNS缓存 System.Diagnostics.Process process = new System.Diagnostics.Process(); process.StartInfo.FileName = "ipconfig"; process.StartInfo.Arguments = "/flushdns"; process.StartInfo.CreateNoWindow = true; process.StartInfo.UseShellExecute = false; process.StartInfo.RedirectStandardOutput = true; process.Start(); process.WaitForExit(); string output = process.StandardOutput.ReadToEnd(); // 可以记录output到日志 }

4. 常见问题、排查技巧与进阶优化

即使代码逻辑正确,在实际运行中你仍可能遇到各种问题。下面是我在多次实践中总结的“避坑指南”。

4.1 权限不足导致失败

这是最常见的问题。修改网络配置需要管理员权限。

解决方案

  1. 以管理员身份运行程序:在Visual Studio中调试时,可以右键点击项目 -> “属性” -> “调试” -> 勾选“以管理员身份启动”。发布后的程序,用户也需要右键选择“以管理员身份运行”。
  2. 在清单文件中请求权限:在项目中添加一个应用程序清单文件(app.manifest),找到<requestedExecutionLevel>节点,将其修改为:
    <requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
    这样编译后的程序每次启动都会自动请求管理员权限。

4.2 网卡描述名不匹配或含有特殊字符

通过描述名查找网卡是脆弱的。不同语言的操作系统、不同版本的驱动,描述名可能不同(如中文“以太网” vs 英文“Ethernet”)。描述名中的括号也可能导致WQL查询语法错误。

解决方案

  1. 使用网卡索引(Index)或GUIDWin32_NetworkAdapterConfigurationIndex属性或Win32_NetworkAdapterGUID属性更稳定。你可以先通过GetAllNetworkAdapters方法列出所有信息,让用户选择Index,然后用SELECT * FROM Win32_NetworkAdapterConfiguration WHERE Index = {index}来查询。
  2. 对描述名进行转义:在构建WQL查询时,如果描述名包含单引号,需要替换为两个单引号。
    string escapedDescription = TargetAdapterDescription.Replace("'", "''"); string query = $"SELECT * FROM Win32_NetworkAdapterConfiguration WHERE Description = '{escapedDescription}'";

4.3 设置网关失败,错误码84(IP正在使用)或网关不可达

SetGateways方法可能因为网关地址与设置的IP不在同一网段,或者网关设备本身不响应ARP请求而失败。

排查步骤

  1. 计算网段:确认你设置的静态IP和子网掩码所确定的网络地址,与网关地址的网络地址是否一致。例如,IP192.168.1.100,掩码255.255.255.0,网络地址是192.168.1.0。网关192.168.1.1的网络地址也是192.168.1.0,这是正确的。如果网关是192.168.2.1,则不在同一网段。
  2. 预先Ping测试(需谨慎):在代码设置前,可以尝试Ping一下目标网关。但注意,有些网关禁Ping,所以Ping不通不代表网关无效。这只能作为参考。
  3. 检查IP冲突:错误码84也可能指你设置的静态IP与网络中其他设备冲突。可以在命令行用arp -a查看,或者暂时将IP改为一个非常用地址测试。

4.4 配置后网络连接断开或出现感叹号

这通常是因为DNS设置有问题,或者IP/网关配置错误导致系统无法访问网络位置感知服务。

处理流程

  1. 首先检查DNS:这是最常见的原因。确保你设置的DNS服务器地址是有效的、可访问的。可以尝试设置为公共DNS,如8.8.8.8114.114.114.114
  2. 使用netsh命令重置:当程序配置出错导致网络异常时,可以用管理员命令行快速重置:
    netsh interface ip set address name="以太网" source=dhcp netsh interface ip set dns name="以太网" source=dhcp
    将“以太网”替换为你的网络连接名称。
  3. 在代码中增加回退机制:在ConfigureStaticIP方法中,如果设置DNS失败,可以考虑不将其作为整体失败的条件,而是记录警告。因为即使DNS设置失败,IP和网关正确,网络通常仍是连通的(只是无法解析域名)。

4.5 多网卡环境下的精准定位

在服务器或有多块网卡的PC上,精准定位目标网卡至关重要。

进阶策略

  1. 结合MAC地址:MAC地址是全球唯一的。你可以让用户提供目标网卡的MAC地址(忽略分隔符),然后通过WMI查询Win32_NetworkAdapter(注意不是Configuration)来获取对应的IndexGUID,再进行配置。
    string query = $"SELECT * FROM Win32_NetworkAdapter WHERE MACAddress = '{macAddress}'"; // 获取到的ManagementObject有一个`Index`属性,与Win32_NetworkAdapterConfiguration的`Index`对应。
  2. 使用网络接口类型:通过System.Net.NetworkInformation.NetworkInterface类,可以获取接口类型(如EthernetWireless80211),结合其他信息进行筛选。

4.6 完整的、健壮的示例源码

以下是一个整合了上述所有考量的、相对健壮的NetworkConfigurator类完整示例,以及一个使用示例。

NetworkConfigurator.cs

using System; using System.Collections.Generic; using System.Linq; using System.Management; namespace StaticIPSetter.Core { public class NetworkConfigurator { public string TargetAdapterDescription { get; private set; } public int? TargetAdapterIndex { get; private set; } /// <summary> /// 通过网卡描述构造(易受语言和驱动影响) /// </summary> public NetworkConfigurator(string adapterDescription) { if (string.IsNullOrWhiteSpace(adapterDescription)) throw new ArgumentException("网卡描述不能为空。"); TargetAdapterDescription = adapterDescription; } /// <summary> /// 通过网卡索引构造(更稳定) /// </summary> public NetworkConfigurator(int adapterIndex) { TargetAdapterIndex = adapterIndex; } private ManagementObject GetNetworkAdapterManagementObject() { string query; if (TargetAdapterIndex.HasValue) { query = $"SELECT * FROM Win32_NetworkAdapterConfiguration WHERE Index = {TargetAdapterIndex.Value}"; } else { string escapedDescription = TargetAdapterDescription.Replace("'", "''"); query = $"SELECT * FROM Win32_NetworkAdapterConfiguration WHERE Description = '{escapedDescription}' AND IPEnabled = TRUE"; } using (ManagementObjectSearcher searcher = new ManagementObjectSearcher(query)) { ManagementObjectCollection collection = searcher.Get(); var mo = collection.OfType<ManagementObject>().FirstOrDefault(); if (mo == null) { string msg = TargetAdapterIndex.HasValue ? $"未找到索引为 {TargetAdapterIndex.Value} 的网络适配器配置。" : $"未找到描述为 '{TargetAdapterDescription}' 的已启用IP的网络适配器。"; throw new InvalidOperationException(msg); } // 注意:这里返回的ManagementObject需要在调用者处Dispose,或者克隆一份。 // 为了简便,我们返回它,并在公共方法中使用using。 return mo; } } public bool SetStaticIP(string ipAddress, string subnetMask) { // ... 参数检查和实现同上文 ... using (var mo = GetNetworkAdapterManagementObject()) { // ... 调用EnableStatic ... } } public bool SetGateway(string gateway, int gatewayMetric = 1) { // ... 参数检查和实现同上文 ... using (var mo = GetNetworkAdapterManagementObject()) { // ... 调用SetGateways ... } } public bool SetDnsServers(string primaryDns, string secondaryDns = null) { // ... 参数检查和实现同上文 ... using (var mo = GetNetworkAdapterManagementObject()) { // ... 调用SetDNSServerSearchOrder ... } } public bool EnableDhcp() { using (var mo = GetNetworkAdapterManagementObject()) { ManagementBaseObject outParams = mo.InvokeMethod("EnableDHCP", null, null); uint returnValue = (uint)outParams["ReturnValue"]; return returnValue == 0; } } public static List<NetworkAdapterInfo> GetAllAdapterInfo() { var list = new List<NetworkAdapterInfo>(); ManagementObjectSearcher searcher = new ManagementObjectSearcher( "SELECT Index, Description, MACAddress, IPAddress, IPSubnet, DefaultIPGateway, DNSServerSearchOrder FROM Win32_NetworkAdapterConfiguration WHERE IPEnabled = TRUE"); foreach (ManagementObject mo in searcher.Get()) { var info = new NetworkAdapterInfo { Index = Convert.ToInt32(mo["Index"]), Description = mo["Description"]?.ToString(), MACAddress = mo["MACAddress"]?.ToString(), IPAddresses = (string[])(mo["IPAddress"] ?? new string[0]), Subnets = (string[])(mo["IPSubnet"] ?? new string[0]), Gateways = (string[])(mo["DefaultIPGateway"] ?? new string[0]), DnsServers = (string[])(mo["DNSServerSearchOrder"] ?? new string[0]) }; list.Add(info); } return list; } } public class NetworkAdapterInfo { public int Index { get; set; } public string Description { get; set; } public string MACAddress { get; set; } public string[] IPAddresses { get; set; } public string[] Subnets { get; set; } public string[] Gateways { get; set; } public string[] DnsServers { get; set; } public override string ToString() { string ip = IPAddresses.Length > 0 ? IPAddresses[0] : "N/A"; string gw = Gateways.Length > 0 ? Gateways[0] : "N/A"; return $"[{Index}] {Description} - IP: {ip}, GW: {gw}, MAC: {MACAddress}"; } } }

Program.cs (使用示例)

using System; using StaticIPSetter.Core; namespace StaticIPSetter { class Program { static void Main(string[] args) { Console.WriteLine("=== 网络适配器列表 ==="); var adapters = NetworkConfigurator.GetAllAdapterInfo(); for (int i = 0; i < adapters.Count; i++) { Console.WriteLine($"{i}: {adapters[i]}"); } if (adapters.Count == 0) { Console.WriteLine("未找到可用的网络适配器。"); return; } Console.Write("\n请选择要配置的适配器编号: "); if (int.TryParse(Console.ReadLine(), out int selectedIndex) && selectedIndex >= 0 && selectedIndex < adapters.Count) { var selectedAdapter = adapters[selectedIndex]; Console.WriteLine($"\n已选择: {selectedAdapter.Description}"); // 使用Index进行初始化,比描述更可靠 var configurator = new NetworkConfigurator(selectedAdapter.Index); Console.WriteLine("\n请输入新的网络配置:"); Console.Write("静态IP地址 (例如 192.168.1.100): "); string ip = Console.ReadLine(); Console.Write("子网掩码 (例如 255.255.255.0): "); string mask = Console.ReadLine(); Console.Write("默认网关 (例如 192.168.1.1): "); string gateway = Console.ReadLine(); Console.Write("主DNS服务器 (例如 8.8.8.8): "); string dns1 = Console.ReadLine(); Console.Write("备用DNS服务器 (可选,直接回车跳过): "); string dns2 = Console.ReadLine(); if (string.IsNullOrWhiteSpace(dns2)) dns2 = null; try { Console.WriteLine("\n开始配置..."); bool success = true; success &= configurator.SetStaticIP(ip, mask); success &= configurator.SetGateway(gateway); success &= configurator.SetDnsServers(dns1, dns2); if (success) { Console.WriteLine("✅ 网络配置成功!"); Console.WriteLine($" IP: {ip}"); Console.WriteLine($" 掩码: {mask}"); Console.WriteLine($" 网关: {gateway}"); Console.WriteLine($" DNS: {dns1}, {dns2 ?? "未设置"}"); } else { Console.WriteLine("❌ 配置过程中部分操作失败。建议检查参数或手动重置为DHCP。"); Console.WriteLine("是否要恢复为DHCP自动获取? (y/N): "); if (Console.ReadLine()?.ToLower() == "y") { if (configurator.EnableDhcp()) Console.WriteLine("已恢复DHCP。"); } } } catch (Exception ex) { Console.WriteLine($"❌ 配置过程中发生错误: {ex.Message}"); } } else { Console.WriteLine("输入无效。"); } Console.WriteLine("\n按任意键退出..."); Console.ReadKey(); } } }

这个示例提供了一个相对完整的命令行工具。在实际产品中,你可以将其封装为DLL,供GUI程序(如WPF/WinForms)调用,并添加更丰富的配置选项(如多IP绑定、设置WINS服务器等)。记住,操作网络配置是敏感行为,务必在UI上给予用户清晰的操作确认和结果反馈。

http://www.cnnetsun.cn/news/3699702.html

相关文章:

  • 狼群算法在柔性车间调度中的Matlab实现与应用
  • Java+Vue声纹识别门禁系统开发实践
  • C++ this指针:从隐式参数到对象模型核心机制详解
  • 影刀RPA完全指南:RPA流程系统测试规范与发布SOP完整手册
  • goimports-reviser vs goimports:为什么这款工具能提升你30%的开发效率?
  • 电竞显示器优化与《龙珠Z》主题定制指南
  • 基于3D打印机改造的自动冰球机器人:视觉识别与运动控制实践
  • 如何使用Backslash Powered Scanner发现JSON注入与服务器端请求伪造漏洞
  • C语言printf打印double输出0.000000:类型不匹配的底层原理与解决方案
  • Transformer自注意力机制原理与工程实践详解
  • 10分钟上手py-junos-eznc:从安装到执行第一个网络自动化任务
  • 基于Matlab的智能停车位识别系统设计与实现
  • mutation-summary性能优化:提升DOM监控效率的10个技巧
  • Linux软件管理与内核升级实战:从rpm/yum到编译安装的深度解析
  • 深入理解C++11内存模型:原子操作、内存序与无锁编程实战
  • OpCore-Simplify终极指南:5分钟完成黑苹果EFI自动配置的完整解决方案
  • Gorilla压缩算法在mandodb中的应用:如何将16字节数据点压缩至1.37字节
  • Java项目代码保护实战:使用JarProtector进行加壳加密与反编译防护
  • 终极SSH暴力攻击防护工具:DenyHosts完全指南 — 从安装到部署的安全守护
  • 阿里Page Agent实战:用自然语言驱动Web交互的前端AI智能体
  • 程序员薪资增长策略与技术栈市场趋势分析
  • 小学信息科技“过程与控制”单元教学:从生活实例到计算思维培养
  • Drive-JEPA:视觉预测与自动驾驶规划的端到端融合
  • 工程化AI编程助手:Claude Code提示词系统定制与复用指南
  • Python物理模拟实战:用Pygame实现飞轮动图生成
  • AngularEditor常见问题解答:开发者必知的15个解决方案
  • Kibitzr:您的终极个人网页助手,5分钟实现网页内容监控与自动通知
  • Arduino光控温控实验:从传感器到执行器的智能家居入门实践
  • 29岁离职程序员,在家半年,继续布局30岁退路。
  • 开源3D打印机器人RAPIRO:从设计到组装的完整实践指南