Search code examples
c#.netnicinterface-metric

Can you change the Interface Metric on a NIC using C#?


The Interface Metric can be changed manually by going into the NIC properties and selecting the "Internet Protocol Version 4 (TCP/IPv4)" properties and then clicking "Advanced".

The Interface Metric is used by the system to prioritize which NIC to use.

Anyway, I'm writing a test where I need to switch back and forth between NICs that are on the same Subnet so that I can control which connection on an external device I am using. (the external device has a single IP Address, but can be accessed via Wired or Wifi) I need to test both of these connections.

So, how can I modify the Interface Metric on one of the NICs programatically in C# through .net? I've seen examples in C++, but the I am looking for a way using C# with .net to do it. I'm trying to write clean code without pushing older libraries into it.


Solution

  • I found a VERY easy way to do this in C# using netsh.exe.

    This only works if you are running your program as administrator.

    The command line is:

    netsh.exe interface ipv4 set interface "myNICsName" metric=20
    

    To set the metric to 'Automatic' just set it to 0. The high limit is 9999, but if you use something higher, it will just set it to 9999 for you.

    To do this programatically, just use Process.Start in the following way:

            System.Diagnostics.Process p = new System.Diagnostics.Process
            {
                StartInfo =
                {
                    FileName = "netsh.exe",
                    Arguments = $"interface ipv4 set interface \"{nicName}\" metric={metric}",
                    UseShellExecute = false,
                    RedirectStandardOutput = true
                }
            };
    
            bool started = p.Start();
    
            if (started)
            {
                if (SpinWait.SpinUntil(() => p.HasExited, TimeSpan.FromSeconds(20)))
                {
                    Log.Write($"Successfully set {nicName}'s metric to {metric}");
                    Log.Write($"Sleeping 2 seconds to allow metric change on {nicName} to take effect.");
                    Thread.Sleep(2000);
    
                    return true;
                }
    
                Log.Write($"Failed to set {nicName}'s metric to {metric}");
                return false;
            }
    

    The above code also does some error checking to make sure the process indeed started and puts in a short delay so that the metric change can have a chance to take effect. I found that I had some problems in my code when I didn't include the delay.