10

I'm coding an application that has to get the network adapters configuration on a Windows 7 machine just like it's done in the Windows network adapters configuration panel:

enter image description here

So far I can get pretty much all the information I need from NetworkInterface.GetAllNetworkInterfaces() EXCEPT the subnet prefix length.

I'm aware that it can be retrieved from the C++ struc PMIB_UNICASTIPADDRESS_TABLE via OnLinkPrefixLength but I'm trying to stay in .net.

I also took a look at the Win32_NetworkAdapterConfiguration WMI class but it only seems to return the IP v4 subnet mask.

I also know that some information (not the prefix length, as far as I know) are in the registry:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\TCPIP6\Parameters\Interfaces\{CLSID}

I also used SysInternals ProcessMon to try to get anything usefull when saving the network adapter settings but found nothing...

So, is there any clean .NET way to get this value? (getting it from the registry wouldn't be a problem)

EDIT: Gateways

This doesn't concern the actual question, but for those who need to retrieve the entire network adapter IPv6 configuration, the IPInterfaceProperties.GatewayAdresses property only supports the IPv4 gateways. As mentionned in the answer comments below, the only way to get the entire info until .NET framework 4.5 is to call WMI.

PhilDulac
  • 1,305
  • 20
  • 32
  • This might help steer you, not sure if it will, but I was able to pull information from the registry. See if this helps: http://stackoverflow.com/questions/1537908/getting-service-tag-from-dell-machine-using-net – JonH Aug 06 '12 at 18:53
  • Like I said, I already watched in the registry if I could find something usefull, but I didn't... :( – PhilDulac Aug 06 '12 at 18:57
  • okay good luck just thought i'd chime in. – JonH Aug 06 '12 at 18:57
  • Check this out: http://stackoverflow.com/questions/3679652/is-ip-address-on-the-same-subnet-as-the-local-machine-with-ipv6-support – Justin Skiles Aug 06 '12 at 21:47
  • 1
    Also, I'm fairly certain that 99.9% of all ipv6 subnets have a prefix length of /64. – Justin Skiles Aug 06 '12 at 21:48
  • RFC 5375: "Using a subnet prefix length other than a /64 will break many features of IPv6". – Justin Skiles Aug 06 '12 at 21:49
  • 1
    @ jskiles1: Well, I'm not an IP v6 nor a network expert and I understand, after reading RFC 5375 IPv6 Addressing Considerations that other values than 64 is not recommended. The problem is, I have to develop a product that offers the same configuration capabilities as Windows! – PhilDulac Aug 07 '12 at 13:18
  • @jskiles1: I also took a look at the question you are refering, it's nice to know that MS is aware that a property should be added to the framework, but didn't find any way to get the subnet mask length, even in the github projet. I ran the same netsh command the project uses and did get the actual Windows value – PhilDulac Aug 07 '12 at 13:28

2 Answers2

4

You can do so using Win32_NetworkAdapterConfiguration. You might have overlooked it.

IPSubnet will return an array of strings. Use the second value. I didn't have time to whip up some C# code, but I'm sure you can handle it. Using WBEMTEST, I pulled this:

instance of Win32_NetworkAdapterConfiguration
{
    Caption = "[00000010] Intel(R) 82579V Gigabit Network Connection";
    DatabasePath = "%SystemRoot%\\System32\\drivers\\etc";
    DefaultIPGateway = {"192.168.1.1"};
    Description = "Intel(R) 82579V Gigabit Network Connection";
    DHCPEnabled = TRUE;
    DHCPLeaseExpires = "20120808052416.000000-240";
    DHCPLeaseObtained = "20120807052416.000000-240";
    DHCPServer = "192.168.1.1";
    DNSDomainSuffixSearchOrder = {"*REDACTED*"};
    DNSEnabledForWINSResolution = FALSE;
    DNSHostName = "*REDACTED*";
    DNSServerSearchOrder = {"192.168.1.1"};
    DomainDNSRegistrationEnabled = FALSE;
    FullDNSRegistrationEnabled = TRUE;
    GatewayCostMetric = {0};
    Index = 10;
    InterfaceIndex = 12;
    IPAddress = {"192.168.1.100", "fe80::d53e:b369:629a:7f95"};
    IPConnectionMetric = 10;
    IPEnabled = TRUE;
    IPFilterSecurityEnabled = FALSE;
    IPSecPermitIPProtocols = {};
    IPSecPermitTCPPorts = {};
    IPSecPermitUDPPorts = {};
    IPSubnet = {"255.255.255.0", "64"};
    MACAddress = "*REDACTED*";
    ServiceName = "e1iexpress";
    SettingID = "{B102679F-36AD-4D80-9D3B-D18C7B8FBF24}";
    TcpipNetbiosOptions = 0;
    WINSEnableLMHostsLookup = TRUE;
    WINSScopeID = "";
};

IPSubnet[1] = IPv6 subnet;

Edit: Here's some code.

StringBuilder sBuilder = new StringBuilder();
ManagementObjectCollection objects = new ManagementObjectSearcher("SELECT * FROM Win32_NetworkAdapterConfiguration").Get();
foreach (ManagementObject mObject in objects)
{
    string description = (string)mObject["Description"];
    string[] addresses = (string[])mObject["IPAddress"];
    string[] subnets = (string[])mObject["IPSubnet"];
    if (addresses == null && subnets == null)
        continue;
    sBuilder.AppendLine(description);
    sBuilder.AppendLine(string.Empty.PadRight(description.Length,'-'));
    if (addresses != null)
    {
        sBuilder.Append("IPv4 Address: ");
        sBuilder.AppendLine(addresses[0]);
        if (addresses.Length > 1)
        {
            sBuilder.Append("IPv6 Address: ");
            sBuilder.AppendLine(addresses[1]);
        }
    }
    if (subnets != null)
    {
        sBuilder.Append("IPv4 Subnet:  ");
        sBuilder.AppendLine(subnets[0]);
        if (subnets.Length > 1)
        {
            sBuilder.Append("IPv6 Subnet:  ");
            sBuilder.AppendLine(subnets[1]);
        }
    }
    sBuilder.AppendLine();
    sBuilder.AppendLine();
}
string output = sBuilder.ToString().Trim();
MessageBox.Show(output);

and some output:

Intel(R) 82579V Gigabit Network Connection
------------------------------------------
IPv4 Address: 192.168.1.100
IPv6 Address: fe80::d53e:b369:629a:7f95
IPv4 Subnet:  255.255.255.0
IPv6 Subnet:  64

Edit: I'm just going to clarify in case somebody searches for this later. The second item isn't always the IPv6 value. IPv4 can have multiple addresses and subnets. Use Integer.TryParse on the IPSubnet array value to make sure it's an IPv6 subnet and/or use the last item.

ShortFuse
  • 5,970
  • 3
  • 36
  • 36
  • Well, I did indeed overlook the WMI class. Will try this tonigth and mark it as answer. The only cons is that WMI isn't quite a performance emblem, the first call takes forever... – PhilDulac Aug 07 '12 at 18:38
  • Well, I didn't write this with speed in mind or search for a specific object. The Foreach command is not very speed efficient. Also, using a WHERE statement in my WMI search would narrow it down to the correct network interface. Regardless, on my machine, it took 5ms to get all the objects and 32ms to iterate through every network connection (which were about 15). I don't think you have to worry about performance. – ShortFuse Aug 07 '12 at 18:56
  • Just a small reminder, a device can have multiple IPv4 addresses and multiple IPv4 subnets. It isn't guaranteed that the second item in the IPSubnet array is IPv6 subnet. You should probably do a Integer.TryParse on the subnet and/or use the last item in the array. – ShortFuse Aug 07 '12 at 19:01
  • It seems there are some fixes coming in .NET framework 4.5, `IPInterfaceProperties.GatewayAdresses` isn't compatible with IPv6 and will only return IPv4 gateways... IPv6 looks like a semi implemented functionnality... So for now, we will be getting the missing info from WMI – PhilDulac Aug 13 '12 at 18:19
  • Also, be aware that WMI doesn't give information on disconnected device! – PhilDulac Aug 14 '12 at 15:38
  • Also, some interfaces (i.e. dial up) are not listed in WMI since Vista. The most reliable way to get both IPv4 and IPv6 addresses is through IPHLPAPI, [GetAdaptersAddresses](https://msdn.microsoft.com/en-us/library/windows/desktop/aa365915%28v=vs.85%29.aspx) for unicasts and [GetIpForwardTable2](https://msdn.microsoft.com/en-us/library/windows/desktop/aa814416%28v=vs.85%29.aspx) for default gateways – Chris Jun 08 '15 at 08:04
1

Parse the input stream of netsh with arguments:

interface ipv6 show route

Hope this helps!

hanleyhansen
  • 6,304
  • 8
  • 37
  • 73
  • It show the IP v6 prefix length at the end of the IP address, that's a step forward... will check with process/file monitor if I can get where it takes that information and access it from .NET without parsing netsh output! – PhilDulac Aug 07 '12 at 17:23