Search code examples
.netnetwork-programmingperformancecounternetwork-interface

How to programmatically select network card that is connected to the internet in .NET


I want to programmatically select the network card that is connected to the Internet. I need this to monitor how much traffic is going through the card. This is what I use to get the instance names

var category = new PerformanceCounterCategory("Network Interface");
String[] instancenames = category.GetInstanceNames();

And this how instancenames looks on my machine

[0]    "6TO4 Adapter"    
[1]    "Internal"    
[2]    "isatap.{385049D5-5293-4E76-A072-9F7A15561418}"    
[3]    "Marvell Yukon 88E8056 PCI-E Gigabit Ethernet Controller"    
[4]    "isatap.{0CB9C3D2-0989-403A-B773-969229ED5074}"    
[5]    "Local Area Connection - Virtual Network"    
[6]    "Teredo Tunneling Pseudo-Interface"

I want the solution to be robust and work on other PCs, I would also prefer .NET. I found other solutions, but they seem to be more complicated for the purpose

  1. Use C++ or WMI
  2. Parse output of netstat

Is there anything else?

See that I already mentioned some available solutions. I am asking if there is anything else, more simple and robust (i.e. NOT C++, WMI or parsing console application output)


Solution

  • I end up useing WMI and external function call, didn't find any better solution. Here is my code if anybody is interested.

    using System;
    using System.Collections.Generic;
    using System.Diagnostics.Contracts;
    using System.Linq;
    using System.Management;
    using System.Net;
    using System.Net.Sockets;
    using System.Runtime.InteropServices;
    
    using log4net;
    
    namespace Networking
    {
        internal class NetworkCardLocator
        {
            [DllImport("iphlpapi.dll", CharSet = CharSet.Auto)]
            public static extern int GetBestInterface(UInt32 DestAddr, out UInt32 BestIfIndex);
    
            private static ILog log = OperationLogger.Instance();
    
            /// <summary>
            /// Selectes the name of the connection that is used to access internet or LAN
            /// </summary>
            /// <returns></returns>
            internal static string GetConnectedCardName()
            {
                uint idx = GetConnectedCardIndex();
                string query = String.Format("SELECT * FROM Win32_NetworkAdapter WHERE InterfaceIndex={0}", idx);
                var searcher = new ManagementObjectSearcher
                {
                    Query = new ObjectQuery(query)
                };
    
                try
                {
                    ManagementObjectCollection adapterObjects = searcher.Get();
    
                    var names = (from ManagementObject o in adapterObjects
                                 select o["Name"])
                                .Cast<string>()
                                .FirstOrDefault();
    
                    return names;
                }
                catch (Exception ex)
                {
                    log.Fatal(ex);
                    throw;
                }
            }
    
            private static uint GetConnectedCardIndex()
            {
                try
                {
                    string localhostName = Dns.GetHostName();
                    IPHostEntry ipEntry = Dns.GetHostEntry(localhostName);
                    IPAddress[] addresses = ipEntry.AddressList;
                    var address = GetNeededIPAddress(addresses);
                    uint ipaddr = IPAddressToUInt32(address);
                    uint interfaceindex;
                    GetBestInterface(ipaddr, out interfaceindex);
    
                    return interfaceindex;
                }
                catch (Exception ex)
                {
                    log.Fatal(ex);
                    throw;
                }
            }
    
            private static uint IPAddressToUInt32(IPAddress address)
            {
                Contract.Requires<ArgumentNullException>(address != null);
    
                try
                {
                    byte[] byteArray1 = IPAddress.Parse(address.ToString()).GetAddressBytes();
                    byte[] byteArray2 = IPAddress.Parse(address.ToString()).GetAddressBytes();
                    byteArray1[0] = byteArray2[3];
                    byteArray1[1] = byteArray2[2];
                    byteArray1[2] = byteArray2[1];
                    byteArray1[3] = byteArray2[0];
                    return BitConverter.ToUInt32(byteArray1, 0);
                }
                catch (Exception ex)
                {
                    log.Fatal(ex);
                    throw;
                }
            }
    
            private static IPAddress GetNeededIPAddress(IEnumerable<IPAddress> addresses)
            {
                var query = from address in addresses
                            where address.AddressFamily == AddressFamily.InterNetwork
                            select address;
    
                return query.FirstOrDefault();
            }
        }
    }