This question has been asked before here without any clear answer.
I am creating a Windows Service that needs to reconfigure the IPv4 and IPv6 DNS addresses for the active network interface. I got the following code from Kaj's answer to a similiar question which works fine for IPv4 addresses but WMI does not seem to support configuration of IPv6 DNS addresses:
private NetworkInterface GetActiveNetworkInterface()
{
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;
}
private void ConfigureDns(string[] dnsAddresses)
{
var currentInterface = GetActiveNetworkInterface();
if (currentInterface == null) return;
ManagementClass mc = new ManagementClass("Win32_NetworkAdapterConfiguration");
ManagementObjectCollection moc = mc.GetInstances();
foreach (ManagementObject mo in moc)
{
if ((bool)mo["IPEnabled"])
{
if (mo["Description"].ToString().Equals(currentInterface.Description))
{
ManagementBaseObject dnsMo = mo.GetMethodParameters("SetDNSServerSearchOrder");
if (dnsMo != null)
{
dnsMo["DNSServerSearchOrder"] = dnsAddresses;
mo.InvokeMethod("SetDNSServerSearchOrder", dnsMo, null);
}
}
}
}
}
public void SetDns(string ipv4PrimaryAddress, string ipv6PrimaryAddress)
{
ConfigureDns(new string[] { ipv4PrimaryAddress, ipv6PrimaryAddress });
}
public void UnsetDns()
{
ConfigureDns(null);
}
So instead I tried to execute netsh
commands using System.Diagnostics.Process
, as suggested by PaulB but this does not work due to the user privileges on my work pc:
public void SetDns(string ipv4PrimaryAddress, string ipv6PrimaryAddress)
{
var currentNic = GetActiveNetworkInterface();
string setIpv4DnsAddress = $"interface ipv4 set dns name=\"{currentNic.Name}\" static {ipv4PrimaryAddress}";
string setIpv6DnsAddress = $"interface ipv6 set dns name=\"{currentNic.Name}\" static {ipv6PrimaryAddress}";
RunCommand(setIpv4DnsAddress);
RunCommand(setIpv6DnsAddress);
}
public void UnsetDns()
{
var currentNic = GetActiveNetworkInterface();
string setIpv4DnsAddress = $"interface ipv4 set dns name=\"{currentNic.Name}\" dhcp";
string setIpv6DnsAddress = $"interface ipv6 set dns name=\"{currentNic.Name}\" dhcp";
RunCommand(setIpv4DnsAddress);
RunCommand(setIpv6DnsAddress);
}
private void RunCommand(string command)
{
Process proc = new Process();
proc.StartInfo.FileName = "netsh.exe";
proc.StartInfo.UseShellExecute = true;
proc.StartInfo.Verb = "runas";
proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
proc.StartInfo.Arguments = command;
proc.Start();
proc.WaitForExit();
}
I am not able to set any network settings through the command line even if I start it as administrator, so this solution seems to be out of the question. The reason I am able to set the IPv4 settings with WMI is because I do it from within the Windows Service which is run using the LocalSystem account.
Is there any way to set both IPv4 and IPv6 DNS addresses from within my Windows Service?
Is there some new API for interacting Windows network adapter configurations?
Is there anything I have missed regarding WMI?
Is there a way to execute the netsh
commands in a Process
run as LocalSystem without having to enter any credentials?
Sources:
Win32_NetworkAdapterConfiguration class
SetDNSServerSearchOrder method of the Win32_NetworkAdapterConfiguration class