In your code, what is the ConnectionProfile
type? It's difficult to understand the question without a good, minimal, complete code example and a precise explanation of what that code does and why that's different from what you want.
That said, if I understand the question correctly, you are trying to determine if your connection to the Internet supports both IPv4 and IPv6. If so, then I don't see any way you could do this from the API level. The local PC could in fact have the IPv4 protocol installed without being attached to a network that would allow traffic on that protocol to be transmitted. Even if the LAN supported that protocol, there could be something about the Internet connection itself that supported only IPv6.
Same thing applies the other way (i.e. having local IPv6 support, but only IPv4 over the Internet).
It seems to me that the only reliable approach is the same as is needed in many other situations: just try it and see if it works. I.e. attempt to connect to your remote endpoint on the Internet via the desired protocol version; if it fails, then it's not supported. If it succeeds, it is supported.
EDIT:
Thanks for the update to the question. It's still not really the best code example, but it refines the question a little.
I'm still not 100% what you need to do, nor whether I have the most useful approach for you. But here is a short program that I think does what you want:
XAML:
<Page x:Class="TestSO32781692NetworkProtocolConnectivity.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:TestSO32781692NetworkProtocolConnectivity"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
DataContext="{Binding RelativeSource={RelativeSource Mode=Self}}"
mc:Ignorable="d">
<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<StackPanel.Resources>
<Style TargetType="TextBlock">
<Setter Property="FontSize" Value="24"/>
</Style>
</StackPanel.Resources>
<StackPanel Orientation="Horizontal" Margin="10, 50, 10, 0">
<TextBlock Text="IpV4: "/>
<TextBlock Text="{Binding IpV4}"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="10, 10, 10, 0">
<TextBlock Text="IpV6: "/>
<TextBlock Text="{Binding IpV6}"/>
</StackPanel>
<Button Content="Check Network" Click="Button_Click"/>
<ListBox ItemsSource="{Binding Profiles}"/>
</StackPanel>
</Page>
C#:
using System;
using System.Collections.ObjectModel;
using System.Linq;
using Windows.Networking;
using Windows.Networking.Connectivity;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
namespace TestSO32781692NetworkProtocolConnectivity
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class MainPage : Page
{
public static readonly DependencyProperty IpV4Property = DependencyProperty.Register(
"IpV4", typeof(bool), typeof(MainPage), new PropertyMetadata(false));
public static readonly DependencyProperty IpV6Property = DependencyProperty.Register(
"IpV6", typeof(bool), typeof(MainPage), new PropertyMetadata(false));
public static readonly DependencyProperty ProfilesProperty = DependencyProperty.Register(
"Profiles", typeof(ObservableCollection<string>), typeof(MainPage), new PropertyMetadata(new ObservableCollection<string>()));
public bool IpV4
{
get { return (bool)GetValue(IpV4Property); }
set { SetValue(IpV4Property, value); }
}
public bool IpV6
{
get { return (bool)GetValue(IpV6Property); }
set { SetValue(IpV6Property, value); }
}
public ObservableCollection<string> Profiles
{
get { return (ObservableCollection<string>)GetValue(ProfilesProperty); }
set { SetValue(ProfilesProperty, value); }
}
public MainPage()
{
this.InitializeComponent();
}
private async void Button_Click(object sender, RoutedEventArgs e)
{
bool ipV4 = false, ipV6 = false;
ConnectionProfile internetProfile = NetworkInformation.GetInternetConnectionProfile();
Profiles.Clear();
Profiles.Add("Internet profile: " + internetProfile.ProfileName);
var hostNames = NetworkInformation.GetHostNames()
.Where(h => h.IPInformation != null &&
h.IPInformation.NetworkAdapter != null);
foreach (HostName hostName in hostNames)
{
ConnectionProfile hostConnectedProfile =
await hostName.IPInformation.NetworkAdapter.GetConnectedProfileAsync();
if (hostConnectedProfile.NetworkAdapter.NetworkAdapterId == internetProfile.NetworkAdapter.NetworkAdapterId)
{
Profiles.Add("Host adapter: " + hostName.DisplayName);
if (hostName.Type == HostNameType.Ipv4)
{
ipV4 = true;
}
else if (hostName.Type == HostNameType.Ipv6)
{
ipV6 = true;
}
}
}
IpV4 = ipV4;
IpV6 = ipV6;
}
}
}
Note that this code example does not use the NetworkInformation.GetConnectionProfiles()
method. Though that seemed like a promising way to extend your current approach, and though the documentation actually promises that "Calling the GetConnectionProfiles method retrieves profiles for all connections currently established on the device, including the Internet connection." [emphasis mine], this turns out to not be the case. In particular, at least on my machine where Hyper-V is installed and enabled (a common scenario for those doing WinRT/Windows Phone development :) ), the ConnectionProfile
object returned by NetworkInformation.GetInternetConnectionProfile()
is in fact not included in the collection of profiles returned by NetworkInformation.GetConnectionProfiles()
.
So instead, what the code example above does is to simply identify any host name objects that appear to correspond with the ConnectionProfile
returned by GetInternetConnectionProfile()
.
Unfortunately, I don't actually have IPv6 support where I am, so I was unable to test this fully. I was able to test the above on a different network where IPv6 to the Internet is supported, and I can now confirm that, at least in my test, it works as expected. The code correctly detects Internet connectivity on both the IPv4 and IPv6 protocols. I'm hopeful that the above does what you need.
By the way, besides the obvious problem that (as you noted) using GetNetworkConnectivityLevel()
does not provide the actual protocol in use, I found that that method does not even return information that at least intuitively would be considered correct.
In particular, calling FindConnectionProfilesAsync(new ConnectionProfileFilter { IsConnected = true })
does return the profile corresponding to the connection (e.g. wireless network) I'm using to connect to the Internet, but when I call GetNetworkConnectivityLevel()
on that profile, it returns LocalAccess
only. I'm guessing this is related to the issue I noted above with having Hyper-V installed.
This can be worked around by comparing the ConnectionProfile
returned by the GetConnectedProfileAsync()
method for the NetworkAdapter
of each connected profile returned by FindConnectionProfilesAsync()
to the profile returned by GetInternetConnectionProfile()
. Indirecting on the profile for the top-level profile's network adapter seems to yield the expected Internet connection profile.
Of course, working around that issue does not solve the question of the protocol in use. I mention it only in the event someone else is looking at this answer more for the profile-management aspects and not the protocol connectivity question.