1 前言
近日由于一些业务需求,需要使用一个在Windows平台使用的IP地址配置管理工具,该文记录了一些开发过程中碰到的问题及解决方案,并附带相关的C#逻辑处理代码。该项目使用WPF框架编写。
2 开发环境
操作系统:Windows 10 开发工具:Visual Studio 2022 目标使用环境:Windows 10/Windows 7 开发要求:开箱即用
3 代码逻辑
3.1 获取网卡信息
private static List<NetworkInterface> GetNetworkInfo()
{
List<NetworkInterface> result = new List<NetworkInterface>();
foreach(NetworkInterface adapter in NetworkInterface.GetAllNetworkInterfaces())
{
result.Add(adapter);
}
return result;
}
使用这个函数可以获取到一个由NetworkInterface组成的列表,NetworkInterface类返回包括网卡的Name、Id、Description等。上诉的三个成员在接下来的功能中将会被用到。
3.2 设置显示网卡信息(IP、DNS、DHCP、子网掩码、MAC地址)
private void SetAdapterInfo(NetworkInterface adapter)
{
IPInterfaceProperties ip = adapter.GetIPProperties();
UnicastIPAddressInformationCollection ipCollection = ip.UnicastAddresses;
foreach (UnicastIPAddressInformation item in ipCollection)
{
if (item.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
{
IpAddress.Text = item.Address.ToString();
subnetMask.Text = item.IPv4Mask.ToString();
}
}
if (ip.DnsAddresses.Count > 0)
{
DNS.Text = ip.DnsAddresses[0].ToString();
if (ip.DnsAddresses.Count > 1)
{
DNS2.Text = ip.DnsAddresses[1].ToString();
}
else
{
DNS2.Text = "备用DNS不存在!";
}
}
else
{
DNS.Text = "DNS不存在!";
DNS2.Text = "备用DNS不存在!";
}
Gateway.Text = GetGateWay(ip);
if (ip.DhcpServerAddresses.Count > 0)
{
DHCPServer.Text = ip.DhcpServerAddresses.FirstOrDefault().ToString();
}
else
{
DHCPServer.Text = "DHCP服务不存在!";
}
PhysicalAddress pa = adapter.GetPhysicalAddress();
byte[] bytes = pa.GetAddressBytes();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < bytes.Length; i++)
{
sb.Append(bytes[i].ToString("X2"));
if (i != bytes.Length - 1)
{
sb.Append('-');
}
}
MAC.Text = sb.ToString();
IsAutoSelector.SelectedIndex = 0;
}
上面的函数中使用了一些TextBox类与ComBox类实例,与UI展示相关。其中IsAutoSelector是设置是否自动配置的ComBox,0是我默认设置的,这个ComBox的ComBoxItem的第一个显示是自动设置;
private string GetGateWay(IPInterfaceProperties ip)
{
string gateWay = "网关信息不存在!";
GatewayIPAddressInformationCollection gateways = ip.GatewayAddresses;
foreach(GatewayIPAddressInformation gateway in gateways)
{
if (IsPingIP(gateway.Address.ToString()))
{
gateWay = gateway.Address.ToString();
break;
}
}
return gateWay;
}
private static bool IsPingIP(string ip)
{
try
{
Ping ping = new Ping();
PingReply reply = ping.Send(ip, 1000);
if(reply != null) { return true; }else { return false; }
}catch
{
return false;
}
}
3.3 开启DHCP服务(自动获取IP、网关、DNS)
private static void EnableDHCP(NetworkInterface adapter)
{
ManagementClass wmi = new ManagementClass("Win32_NetworkAdapterConfiguration");
ManagementObjectCollection moc = wmi.GetInstances();
foreach (ManagementObject m in moc)
{
if (!(bool)m["IPEnabled"])
continue;
if(m["SettingID"].ToString() == adapter.Id)
{
m.InvokeMethod("SetDNSServerSearchOrder", null);
m.InvokeMethod("EnableDHCP", null);
MessageBox.Show("已设置自动获取!");
}
}
}
3.4 开启/关闭网卡
private static ManagementObject GetNetwork(NetworkInterface adapter)
{
string netState = "SELECT * From Win32_NetworkAdapter";
ManagementObjectSearcher searcher = new ManagementObjectSearcher(netState);
ManagementObjectCollection moc = searcher.Get();
foreach (ManagementObject m in moc)
{
if(m["Name"].ToString() == adapter.Description)
{
return m;
}
}
return null;
}
private static bool EnableAdapter(ManagementObject m)
{
try
{
m.InvokeMethod("Enable", null);
return true;
}
catch
{
return false;
}
}
private static bool DisableAdapter(ManagementObject m)
{
try
{
m.InvokeMethod("Disable", null);
return true;
}
catch
{
return false;
}
}
3.5 设置IP、DNS、子网掩码
private static bool SetIPAddress(NetworkInterface adapter, string[] ip, string[] submask, string[] gateway, string[] dns)
{
ManagementClass mc = new ManagementClass("Win32_NetworkAdapterConfiguration");
ManagementObjectCollection moc = mc.GetInstances();
string str = "";
foreach(ManagementObject m in moc)
{
if (m["SettingID"].ToString() == adapter.Id)
{
if (ip != null && submask != null)
{
ManagementBaseObject inPar;
ManagementBaseObject outPar;
string caption = m["Caption"].ToString();
inPar = m.GetMethodParameters("EnableStatic");
inPar["IPAddress"] = ip;
inPar["SubnetMask"] = submask;
outPar = m.InvokeMethod("EnableStatic", inPar, null);
str = outPar["returnvalue"].ToString();
if (str != "0" && str != "1")
{
return false;
}
}
if (gateway != null)
{
ManagementBaseObject inPar;
ManagementBaseObject outPar;
string caption = m["Caption"].ToString();
inPar = m.GetMethodParameters("SetGateways");
inPar["DefaultIPGateway"] = gateway;
outPar = m.InvokeMethod("SetGateways", inPar, null);
str = outPar["returnvalue"].ToString();
if (str != "0" && str != "1")
{
return false;
}
}
if(dns != null)
{
ManagementBaseObject inPar;
ManagementBaseObject outPar;
inPar = m.GetMethodParameters("SetDNSServerSearchOrder");
inPar["DNSServerSearchOrder"] = dns;
outPar = m.InvokeMethod("SetDNSServerSearchOrder", inPar, null);
str = outPar["returnvalue"].ToString();
if (str != "0" && str != "1")
{
return false;
}
}
return true;
}
}
return false ;
}
3.6 完整代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Management;
using System.Net.NetworkInformation;
namespace nextseq_utils
{
public partial class MainWindow : Window
{
private readonly List<NetworkInterface> adapters;
public MainWindow()
{
InitializeComponent();
adapters = GetNetworkInfo();
foreach(NetworkInterface adapter in adapters)
{
string Name = adapter.Name;
ComboBoxItem cbi = new ComboBoxItem();
cbi.Content = Name;
AdapterSelector.Items.Add(cbi);
}
}
private static List<NetworkInterface> GetNetworkInfo()
{
List<NetworkInterface> result = new List<NetworkInterface>();
foreach(NetworkInterface adapter in NetworkInterface.GetAllNetworkInterfaces())
{
result.Add(adapter);
}
return result;
}
private NetworkInterface GetAdapterByName(string name)
{
NetworkInterface adapter = null;
foreach(NetworkInterface adapter2 in adapters)
{
if(adapter2.Name == name)
{
adapter = adapter2;
break;
}
}
return adapter;
}
private string GetGateWay(IPInterfaceProperties ip)
{
string gateWay = "网关信息不存在!";
GatewayIPAddressInformationCollection gateways = ip.GatewayAddresses;
foreach(GatewayIPAddressInformation gateway in gateways)
{
if (IsPingIP(gateway.Address.ToString()))
{
gateWay = gateway.Address.ToString();
break;
}
}
return gateWay;
}
private static bool IsPingIP(string ip)
{
try
{
Ping ping = new Ping();
PingReply reply = ping.Send(ip, 1000);
if(reply != null) { return true; }else { return false; }
}catch
{
return false;
}
}
private void SetAdapterInfo(NetworkInterface adapter)
{
IPInterfaceProperties ip = adapter.GetIPProperties();
UnicastIPAddressInformationCollection ipCollection = ip.UnicastAddresses;
foreach (UnicastIPAddressInformation item in ipCollection)
{
if (item.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
{
IpAddress.Text = item.Address.ToString();
subnetMask.Text = item.IPv4Mask.ToString();
}
}
if (ip.DnsAddresses.Count > 0)
{
DNS.Text = ip.DnsAddresses[0].ToString();
if (ip.DnsAddresses.Count > 1)
{
DNS2.Text = ip.DnsAddresses[1].ToString();
}
else
{
DNS2.Text = "备用DNS不存在!";
}
}
else
{
DNS.Text = "DNS不存在!";
DNS2.Text = "备用DNS不存在!";
}
Gateway.Text = GetGateWay(ip);
if (ip.DhcpServerAddresses.Count > 0)
{
DHCPServer.Text = ip.DhcpServerAddresses.FirstOrDefault().ToString();
}
else
{
DHCPServer.Text = "DHCP服务不存在!";
}
PhysicalAddress pa = adapter.GetPhysicalAddress();
byte[] bytes = pa.GetAddressBytes();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < bytes.Length; i++)
{
sb.Append(bytes[i].ToString("X2"));
if (i != bytes.Length - 1)
{
sb.Append('-');
}
}
MAC.Text = sb.ToString();
IsAutoSelector.SelectedIndex = 0;
}
private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
string content = AdapterSelector.SelectedValue.ToString();
content = content.Replace("System.Windows.Controls.ComboBoxItem: ","");
NetworkInterface adapter = GetAdapterByName(content);
if(adapter != null)
{
SetAdapterInfo(adapter);
}
}
private static void EnableDHCP(NetworkInterface adapter)
{
ManagementClass wmi = new ManagementClass("Win32_NetworkAdapterConfiguration");
ManagementObjectCollection moc = wmi.GetInstances();
foreach (ManagementObject m in moc)
{
if (!(bool)m["IPEnabled"])
continue;
if(m["SettingID"].ToString() == adapter.Id)
{
m.InvokeMethod("SetDNSServerSearchOrder", null);
m.InvokeMethod("EnableDHCP", null);
MessageBox.Show("已设置自动获取!");
}
}
}
private void ComboBox_SelectionChanged_1(object sender, SelectionChangedEventArgs e)
{
string content = IsAutoSelector.SelectedValue.ToString();
content = content.Replace("System.Windows.Controls.ComboBoxItem: ", "");
if(content == "自动")
{
IpAddress.IsEnabled = false;
subnetMask.IsEnabled = false;
Gateway.IsEnabled = false;
DNS.IsEnabled = false;
DNS2.IsEnabled = false;
DHCPServer.IsEnabled = false;
SettingIP.IsEnabled = false;
if (IsAutoSelector.Text == "手动")
{
string name = AdapterSelector.SelectedValue.ToString();
name = name.Replace("System.Windows.Controls.ComboBoxItem: ", "");
NetworkInterface adapter = GetAdapterByName(name);
if (adapter != null)
{
EnableDHCP(adapter);
SetAdapterInfo(adapter);
}
}
}
else if(content == "手动")
{
IpAddress.IsEnabled = true;
subnetMask.IsEnabled = true;
Gateway.IsEnabled = true;
DNS.IsEnabled = true;
DNS2.IsEnabled = true;
DHCPServer.IsEnabled = true;
SettingIP.IsEnabled = true;
}
}
private static ManagementObject GetNetwork(NetworkInterface adapter)
{
string netState = "SELECT * From Win32_NetworkAdapter";
ManagementObjectSearcher searcher = new ManagementObjectSearcher(netState);
ManagementObjectCollection moc = searcher.Get();
foreach (ManagementObject m in moc)
{
if(m["Name"].ToString() == adapter.Description)
{
return m;
}
}
return null;
}
private static bool EnableAdapter(ManagementObject m)
{
try
{
m.InvokeMethod("Enable", null);
return true;
}
catch
{
return false;
}
}
private static bool DisableAdapter(ManagementObject m)
{
try
{
m.InvokeMethod("Disable", null);
return true;
}
catch
{
return false;
}
}
private void Button_Click(object sender, RoutedEventArgs e)
{
if(AdapterSelector.Text == "")
{
MessageBox.Show("请选择网卡后操作!");
}
else
{
NetworkInterface adapter = GetAdapterByName(AdapterSelector.Text);
if(adapter != null)
{
if (EnableAdapter(GetNetwork(adapter)))
{
MessageBox.Show("开启网卡成功!");
}
else
{
MessageBox.Show("开启网卡失败!");
};
}
}
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
if (AdapterSelector.Text == "")
{
MessageBox.Show("请选择网卡后操作!");
}
else
{
NetworkInterface adapter = GetAdapterByName(AdapterSelector.Text);
if (adapter != null)
{
if (DisableAdapter(GetNetwork(adapter)))
{
MessageBox.Show("关闭网卡成功!");
}
else
{
MessageBox.Show("关闭网卡失败!");
};
}
}
}
private static bool SetIPAddress(NetworkInterface adapter, string[] ip, string[] submask, string[] gateway, string[] dns)
{
ManagementClass mc = new ManagementClass("Win32_NetworkAdapterConfiguration");
ManagementObjectCollection moc = mc.GetInstances();
string str = "";
foreach(ManagementObject m in moc)
{
if (m["SettingID"].ToString() == adapter.Id)
{
if (ip != null && submask != null)
{
ManagementBaseObject inPar;
ManagementBaseObject outPar;
string caption = m["Caption"].ToString();
inPar = m.GetMethodParameters("EnableStatic");
inPar["IPAddress"] = ip;
inPar["SubnetMask"] = submask;
outPar = m.InvokeMethod("EnableStatic", inPar, null);
str = outPar["returnvalue"].ToString();
if (str != "0" && str != "1")
{
return false;
}
}
if (gateway != null)
{
ManagementBaseObject inPar;
ManagementBaseObject outPar;
string caption = m["Caption"].ToString();
inPar = m.GetMethodParameters("SetGateways");
inPar["DefaultIPGateway"] = gateway;
outPar = m.InvokeMethod("SetGateways", inPar, null);
str = outPar["returnvalue"].ToString();
if (str != "0" && str != "1")
{
return false;
}
}
if(dns != null)
{
ManagementBaseObject inPar;
ManagementBaseObject outPar;
inPar = m.GetMethodParameters("SetDNSServerSearchOrder");
inPar["DNSServerSearchOrder"] = dns;
outPar = m.InvokeMethod("SetDNSServerSearchOrder", inPar, null);
str = outPar["returnvalue"].ToString();
if (str != "0" && str != "1")
{
return false;
}
}
return true;
}
}
return false ;
}
private void Button_Click_2(object sender, RoutedEventArgs e)
{
NetworkInterface adapter = GetAdapterByName(AdapterSelector.Text);
if (adapter != null)
{
string[] ip = { IpAddress.Text };
string[] submask = { subnetMask.Text };
string[] gateway;
if(Gateway.Text != "网关信息不存在!" && Gateway.Text != "")
{
gateway = new string[1];
gateway[0] = Gateway.Text;
}
else
{
gateway = null;
}
string[] dns;
if(DNS.Text != "DNS不存在!" && DNS.Text != "")
{
if(DNS2.Text != "备用DNS不存在!" && DNS2.Text != "")
{
dns = new string[2];
dns[0] = DNS.Text;
dns[1] = DNS2.Text;
}
else
{
dns = new string[1];
dns[0] = DNS.Text;
}
}
else
{
dns = null;
}
if(SetIPAddress(adapter, ip, submask, gateway, dns))
{
MessageBox.Show("设置成功!");
}
else
{
MessageBox.Show("设置失败!");
};
}
}
}
}
3.7 UI代码(xaml)
<Window x:Class="nextseq_utils.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:nextseq_utils"
mc:Ignorable="d"
Title="MainWindow" Height="625" Width="500">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<ComboBox x:Name="AdapterSelector" HorizontalAlignment="Left" Height="30" Margin="192,43,0,0" VerticalAlignment="Top" Width="239" FontSize="14" SelectionChanged="ComboBox_SelectionChanged"/>
<Label HorizontalContentAlignment="Center" Content="网卡" HorizontalAlignment="Left" Height="30" VerticalAlignment="Top" Width="119" Margin="52,43,0,0" FontSize="14"/>
<Label HorizontalContentAlignment="Center" Content="获取IP方式" HorizontalAlignment="Left" Height="30" VerticalAlignment="Top" Width="119" Margin="52,93,0,0" FontSize="14"/>
<ComboBox x:Name="IsAutoSelector" HorizontalAlignment="Left" Height="30" Margin="192,93,0,0" VerticalAlignment="Top" Width="239" FontSize="14" SelectionChanged="ComboBox_SelectionChanged_1">
<ComboBoxItem Content="自动"/>
<ComboBoxItem Content="手动"/>
</ComboBox>
<Label HorizontalContentAlignment="Center" Content="IP地址" HorizontalAlignment="Left" Height="30" VerticalAlignment="Top" Width="119" Margin="52,143,0,0" FontSize="14"/>
<TextBox x:Name="IpAddress" IsEnabled="False" VerticalContentAlignment="Center" HorizontalAlignment="Left" Height="30" Margin="192,143,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="239" FontSize="14"/>
<Label HorizontalContentAlignment="Center" Content="子网掩码" HorizontalAlignment="Left" Height="30" VerticalAlignment="Top" Width="119" Margin="52,193,0,0" FontSize="14"/>
<TextBox x:Name="subnetMask" IsEnabled="False" VerticalContentAlignment="Center" HorizontalAlignment="Left" Height="30" Margin="192,193,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="239" FontSize="14"/>
<Label HorizontalContentAlignment="Center" Content="网关" HorizontalAlignment="Left" Height="30" VerticalAlignment="Top" Width="119" Margin="52,243,0,0" FontSize="14"/>
<TextBox x:Name="Gateway" IsEnabled="False" VerticalContentAlignment="Center" HorizontalAlignment="Left" Height="30" Margin="192,243,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="239" FontSize="14"/>
<Label HorizontalContentAlignment="Center" Content="主DNS" HorizontalAlignment="Left" Height="30" VerticalAlignment="Top" Width="119" Margin="52,294,0,0" FontSize="14"/>
<TextBox x:Name="DNS" IsEnabled="False" VerticalContentAlignment="Center" HorizontalAlignment="Left" Height="30" Margin="192,294,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="239" FontSize="14"/>
<Label HorizontalContentAlignment="Center" Content="备用DNS" HorizontalAlignment="Left" Height="30" VerticalAlignment="Top" Width="119" Margin="52,343,0,0" FontSize="14"/>
<TextBox x:Name="DNS2" IsEnabled="False" VerticalContentAlignment="Center" HorizontalAlignment="Left" Height="30" Margin="192,343,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="239" FontSize="14"/>
<Label HorizontalContentAlignment="Center" Content="DHCP服务器" HorizontalAlignment="Left" Height="30" VerticalAlignment="Top" Width="119" Margin="52,393,0,0" FontSize="14"/>
<TextBox x:Name="DHCPServer" IsEnabled="False" VerticalContentAlignment="Center" HorizontalAlignment="Left" Height="30" Margin="192,393,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="239" FontSize="14"/>
<Label HorizontalContentAlignment="Center" Content="物理地址" HorizontalAlignment="Left" Height="30" VerticalAlignment="Top" Width="119" Margin="52,443,0,0" FontSize="14"/>
<TextBox x:Name="MAC" IsEnabled="False" VerticalContentAlignment="Center" HorizontalAlignment="Left" Height="30" Margin="192,443,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="239" FontSize="14"/>
<Button x:Name="SettingIP" Content="设置IP" IsEnabled="False" HorizontalAlignment="Left" Height="30" Margin="80,502,0,0" VerticalAlignment="Top" Width="100" FontSize="14" Click="Button_Click_2"/>
<Button Content="启用连接" HorizontalAlignment="Left" Height="30" Margin="206,502,0,0" VerticalAlignment="Top" Width="100" FontSize="14" Click="Button_Click" />
<Button Content="禁用连接" HorizontalAlignment="Left" Height="30" Margin="330,502,0,0" VerticalAlignment="Top" Width="100" FontSize="14" Click="Button_Click_1" />
</Grid>
</Window>
4 开发遇到的问题
4.1 运行环境问题
这个工具主要是提供给illumina的测序仪使用的,公司部分测序仪型号比较老,操作系统是windows 7,并且在运行稳定的情况下基本上是不允许升级操作系统或者.Net framework框架的,因此该程序的运行环境必须要降级到.Net 4.0。 注:代码可以与.Net 4.0与.Net 6.0完全兼容,不需要任何改动即可编译运行!兼容性这一块不得不夸赞微软一波! 解决方案: ①安装Visual Studio 生成工具 2019,并勾选.Net 桌面生成工具,安装相关的SDK。 ②在Visual Studio 2022中进行配置。 默认勾选的WPF开发环境目前是.Net 6.0,我们需要对其进行降级。 资源管理器→点击项目→右击→属性 选择完毕后Visual Studio 2022会自动进行相关的配置。该过程不会提示,如果后续发布或者运行过程中仍然是.Net 6.0 可以尝试清理项目后重启Visual Studio重新进行设置。如果没有执行操作①可能会提示没有安装相关的运行环境。
4.2 命名空间“Management”在“System”中不存在
这个问题在不同的运行环境中有不同的解决方案。并且解决方案是完全不同的。 ① .Net 6.0 在该版本的运行环境中,System.Management是作为第三方库存在的。在资源管理器中右击依赖项,点击管理NuGet程序包程序包,搜索System.Management,安装对应的版本的System.Management即可。 ② .Net 4.0 在该版本中,System.Management是作为一个内置的可引用程序集存在。在资源管理器中右击依赖性,点击添加新的引用项,在程序集中下拉,勾选System.Management后点击确定即可。
4.3 以管理员权限运行
该程序需要以管理员权限运行,以下方法亲测有效。 在资源管理中右击Properties→添加→新建项→应用程序清单文件,添加文件,修改app.manifest如下图。
4.4 其他
该部分见代码部分的注释信息。
|