9

I'm trying to change the DNS on Windows 10 through VB.NET.

I have code that works on Windows 7, however it does not work on Windows 10.

Here is my code for Windows 7 that changes the DNS:

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);

My question is, how do I get this to work on Windows 10 OS?

help-info.de
  • 6,695
  • 16
  • 39
  • 41
J doe
  • 91
  • 1
  • 2
  • Does this work on non-Windows 10 versions? What error do you get on Windows 10? – Nate Oct 27 '16 at 18:06
  • 1
    I don't get any errors on Windows 10, it just doesn't change the DNS. But yes this code works for Windows 7 without any issues. – J doe Oct 27 '16 at 18:07
  • Hi Did you try to checkout this question? http://stackoverflow.com/questions/209779/how-can-you-change-network-settings-ip-address-dns-wins-host-name-with-code?noredirect=1&lq=1 – Drew Aguirre May 19 '17 at 10:29
  • Just for my own curiosity, why do you want to change the DNS? – Michael Puckett II May 21 '17 at 14:20

4 Answers4

11

First you need to get the NetworkInterface you want to set/unset DNS

I've tested this code on the latest version of Windows 10 and it works like a charm!

Here is the code to find the active Ethernet or Wifi network (Not 100% accurate but useful in most cases)

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["Description"].ToString().Equals(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["Description"].ToString().Equals(CurrentInterface.Description))
            {
                ManagementBaseObject objdns = objMO.GetMethodParameters("SetDNSServerSearchOrder");
                if (objdns != null)
                {
                    objdns["DNSServerSearchOrder"] = null;
                    objMO.InvokeMethod("SetDNSServerSearchOrder", objdns, null);
                }
            }
        }
    }
}

Usage

SetDNS("127.0.0.1");
Shangwu
  • 1,440
  • 12
  • 12
Mohamad Rashidi
  • 307
  • 2
  • 14
  • I feel this could accidentally set DNS on multiple NICs should the PC have 2 NICs with the same description which I believe is possible. It is usually better to use WMI to get the exact NIC name and then use `["Caption"].Equals` to make sure you have the device you want. – David Bentley Nov 10 '17 at 16:19
  • You must run as administrator. – Think Big Oct 24 '22 at 17:22
2

Combining multiple solutions I found that the following code is working great for Windows 10 and 8.1 (others not tested, but should work as well):

public static void setDNS(string NIC, string DNS)
{
    ConnectionOptions options = PrepareOptions();
    ManagementScope scope = PrepareScope(Environment.MachineName, options, @"\root\CIMV2");
    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;
                }
            }
        }
    }
}

The application needs to run with elevated permissions (in my case I'm starting an elevated process running an .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;
    }
}

Using mo["Caption"].ToString().Contains(NIC) doesn't work for Windows 10 as the WMI query returns the NIC-Name leading with [000000]

[000000] Intel(R) 82574L Gigabit Network Connection

on my Windows 10 machine.

Credit to the following answers: [WMI not working after upgrading to Windows 10

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

and the answers to this question.

adiuva
  • 98
  • 1
  • 11
0

With Windows 10 you may need authentication first. Pass a ConnectionOptions instance to a ManagementScope constructor, defining your Authentication and Impersonation properties.

Try this:

// 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 , @"\root\CIMV2" );
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);

Based on this answer:

WMI not working after upgrading to Windows 10

Community
  • 1
  • 1
Defcode
  • 21
  • 7
  • Unfortunately your code has errors: The two arguments for ManagementClass mc = new ManagementClass(scope, "Wie32[..]") are both marked invalid. Any ideas how to fix it? – adiuva May 13 '17 at 22:31
0

This is the code I use to do this and it works:

/// <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 
            if (objMO["Caption"].Equals(NIC))
            {
                try
                {
                    ManagementBaseObject newDNS =
                        objMO.GetMethodParameters("SetDNSServerSearchOrder");
                    newDNS["DNSServerSearchOrder"] = DNS.Split(',');
                    ManagementBaseObject setDNS =
                        objMO.InvokeMethod("SetDNSServerSearchOrder", newDNS, null);
                }
                catch (Exception)
                {
                    throw;
                }
            }
        }
    }
}

Hope it helps...

Leo
  • 5,013
  • 1
  • 28
  • 65
  • I think it originally came from here : http://stackoverflow.com/questions/209779/how-can-you-change-network-settings-ip-address-dns-wins-host-name-with-code – Leo May 18 '17 at 11:56
  • That's the same code I'm using as well but it doesn't work anymore with Windows 10. – adiuva May 18 '17 at 12:02
  • are you only changing `if (objMO["Caption"].Equals(NIC))`? – Leo May 18 '17 at 12:04
  • are you running elevated / with admin privileges? – Leo May 18 '17 at 12:05
  • Try to disable your firewall and see if the change takes effect then... I seem to remember there were problems with BitDefender and Avast Firewall... Sorry I can't be more specific as i just can't remember the details :) – Leo May 18 '17 at 12:09