如何在Windows 10上使用C#更改DNS

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在Windows 10上使用C#更改DNS相关的知识,希望对你有一定的参考价值。

我正在尝试通过VB.NET更改Windows 10上的DNS。

我有适用于Windows 7的代码,但它在Windows 10上不起作用。

以下是我更改DNS的Windows 7代码:

ManagementClass mc = new ManagementClass("Win32_NetworkAdapterConfiguration");
ManagementObjectCollection moc = mc.GetInstances();
foreach (ManagementObject mo in moc)
{
    if ((bool)mo["IPEnabled"])
    {
        ManagementBaseObject objdns = mo.GetMethodParameters("SetDNSServerSearchOrder");
        if (objdns != null)
        {
            string[] s = { "192.168.XX.X", "XXX.XX.X.XX" };
            objdns["DNSServerSearchOrder"] = s;
            mo.InvokeMethod("SetDNSServerSearchOrder", objdns, null);

我的问题是,如何让它在Windows 10操作系统上运行?

答案

首先,您需要获取要设置/取消设置DNS的NetworkInterface

我已经在最新版本的Windows 10上测试了这段代码,它就像一个魅力!

以下是查找有源以太网或Wifi网络的代码(在大多数情况下不是100%准确但有用)

public static NetworkInterface GetActiveEthernetOrWifiNetworkInterface()
{
    var Nic = NetworkInterface.GetAllNetworkInterfaces().FirstOrDefault(
        a => a.OperationalStatus == OperationalStatus.Up &&
        (a.NetworkInterfaceType == NetworkInterfaceType.Wireless80211 || a.NetworkInterfaceType == NetworkInterfaceType.Ethernet) &&
        a.GetIPProperties().GatewayAddresses.Any(g => g.Address.AddressFamily.ToString() == "InterNetwork"));

    return Nic;
}

SetDNS

public static void SetDNS(string DnsString)
{
    string[] Dns = { DnsString };
    var CurrentInterface = GetActiveEthernetOrWifiNetworkInterface();
    if (CurrentInterface == null) return;

    ManagementClass objMC = new ManagementClass("Win32_NetworkAdapterConfiguration");
    ManagementObjectCollection objMOC = objMC.GetInstances();
    foreach (ManagementObject objMO in objMOC)
    {
        if ((bool)objMO["IPEnabled"])
        {
            if (objMO["Caption"].ToString().Contains(CurrentInterface.Description))
            {
                ManagementBaseObject objdns = objMO.GetMethodParameters("SetDNSServerSearchOrder");
                if (objdns != null)
                {
                    objdns["DNSServerSearchOrder"] = Dns;
                    objMO.InvokeMethod("SetDNSServerSearchOrder", objdns, null);
                }
            }
        }
    }
}

UnsetDNS

public static void UnsetDNS()
{
    var CurrentInterface = GetActiveEthernetOrWifiNetworkInterface();
        if (CurrentInterface == null) return;

    ManagementClass objMC = new ManagementClass("Win32_NetworkAdapterConfiguration");
    ManagementObjectCollection objMOC = objMC.GetInstances();
    foreach (ManagementObject objMO in objMOC)
    {
        if ((bool)objMO["IPEnabled"])
        {
            if (objMO["Caption"].ToString().Contains(CurrentInterface.Description))
            {
                ManagementBaseObject objdns = objMO.GetMethodParameters("SetDNSServerSearchOrder");
                if (objdns != null)
                {
                    objdns["DNSServerSearchOrder"] = null;
                    objMO.InvokeMethod("SetDNSServerSearchOrder", objdns, null);
                }
            }
        }
    }
}

用法

SetDNS("127.0.0.1");
另一答案

结合多个解决方案我发现以下代码适用于Windows 10和8.1(其他代码未经过测试,但也可以正常工作):

public static void setDNS(string NIC, string DNS)
{
    ConnectionOptions options = PrepareOptions();
    ManagementScope scope = PrepareScope(Environment.MachineName, options, @"
ootCIMV2");
    ManagementPath managementPath = new ManagementPath("Win32_NetworkAdapterConfiguration");
    ObjectGetOptions objectGetOptions = new ObjectGetOptions();
    ManagementClass mc = new ManagementClass(scope, managementPath, objectGetOptions);
    ManagementObjectCollection moc = mc.GetInstances();
    foreach (ManagementObject mo in moc)
    {
        if ((bool)mo["IPEnabled"])
        {
            if (mo["Caption"].ToString().Contains(NIC))
            {
                try
                {
                    ManagementBaseObject newDNS = mo.GetMethodParameters("SetDNSServerSearchOrder");
                    newDNS["DNSServerSearchOrder"] = DNS.Split(',');
                    ManagementBaseObject setDNS = mo.InvokeMethod("SetDNSServerSearchOrder", newDNS, null);
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.ToString());
                    Console.ReadKey();
                    throw;
                }
            }
        }
    }
}

应用程序需要以提升的权限运行(在我的情况下,我正在启动运行.exe的提升进程):

private void callSwapDNS(string NIC, string DNS)
{
    const int ERROR_CANCELLED = 1223; //The operation was canceled by the user.
    ProcessStartInfo info = new ProcessStartInfo(@"swap.exe");
    string wrapped = string.Format(@"""{0}"" ""{1}""", NIC, DNS);
    info.Arguments = wrapped;
    info.UseShellExecute = true;
    info.Verb = "runas";
    info.WindowStyle = ProcessWindowStyle.Hidden;
    try
    {
        Process.Start(info);
        Thread.Sleep(500);
    }
    catch (Win32Exception ex)
    {
        if (ex.NativeErrorCode == ERROR_CANCELLED)
            MessageBox.Show("Why you no select Yes?");
        else
            throw;
    }
}

使用mo["Caption"].ToString().Contains(NIC)不适用于Windows 10,因为WMI查询返回带有[000000]的NIC-Name。

[000000] Intel(R)82574L千兆网络连接

在我的Windows 10机器上。

请注意以下答案:[升级到Windows 10后WMI无法正常工作

WMI not working after upgrading to Windows 10 How can you change Network settings (IP Address, DNS, WINS, Host Name) with code in C#

以及这个问题的答案。

另一答案

使用Windows 10,您可能需要先进行身份验证。将ConnectionOptions实例传递给ManagementScope构造函数,定义Authentication和Impersonation属性。

试试这个:

// Method to prepare the WMI query connection options.
public static ConnectionOptions PrepareOptions ( )
{
  ConnectionOptions options = new ConnectionOptions ( );
  options . Impersonation = ImpersonationLevel . Impersonate;
  options . Authentication = AuthenticationLevel . Default;
  options . EnablePrivileges = true;
  return options;
}

// Method to prepare WMI query management scope.
public static ManagementScope PrepareScope ( string machineName , ConnectionOptions options , string path  )
{
  ManagementScope scope = new ManagementScope ( );
  scope . Path = new ManagementPath ( @"\" + machineName + path );
  scope . Options = options;
  scope . Connect ( );
  return scope;
}

// Set DNS.
ConnectionOptions options = PrepareOptions ( );
ManagementScope scope = PrepareScope ( Environment . MachineName , options , @"
ootCIMV2" );
ManagementClass mc = new ManagementClass(scope, "Win32_NetworkAdapterConfiguration");
ManagementObjectCollection moc = mc.GetInstances();
foreach (ManagementObject mo in moc)
{
    if ((bool)mo["IPEnabled"])
    {
        ManagementBaseObject objdns = mo.GetMethodParameters("SetDNSServerSearchOrder");
        if (objdns != null)
        {
            string[] s = { "192.168.XX.X", "XXX.XX.X.XX" };
            objdns["DNSServerSearchOrder"] = s;
            mo.InvokeMethod("SetDNSServerSearchOrder", objdns, null);

根据这个答案:

WMI not working after upgrading to Windows 10

另一答案

这是我用来执行此操作的代码,它可以工作:

/// <summary>
/// Set's the DNS Server of the local machine
/// </summary>
/// <param name="NIC">NIC address</param>
/// <param name="DNS">DNS server address</param>
/// <remarks>Requires a reference to the System.Management namespace</remarks>
public void setDNS(string NIC, string DNS)
{
    ManagementClass objMC = new ManagementClass("Win32_NetworkAdapterConfiguration");
    ManagementObjectCollection objMOC = objMC.GetInstances();

    foreach (ManagementObject objMO in objMOC)
    {
        if ((bool)objMO["IPEnabled"])
        {
            // if you are using the System.Net.NetworkInformation.NetworkInterface you'll need to change this line to if (objMO["Caption"].ToString().Contains(NIC)) and pass in the Description property instead of the name 

以上是关于如何在Windows 10上使用C#更改DNS的主要内容,如果未能解决你的问题,请参考以下文章

如何更改本地机器/以太网 IP 地址

如何在 Windows 上更改 Jenkins 默认文件夹?

如何在电脑上设置dns

dig(DNS Lookup)在Windows上指定DNS服务器

在 Windows 10 Home 上使用 WSL2 上的 Docker Desktop 时,如何更改 docker 映像的位置?

如何让代码在 Windows 10 上的 GPU 上运行?