在您的代码中,ConnectionProfile 类型是什么?如果没有a good, minimal, complete code example 以及对该代码的作用以及为什么与您想要的不同的确切解释,很难理解这个问题。
也就是说,如果我正确理解了这个问题,您正在尝试确定您与 Internet 的连接是否同时支持 IPv4 和 IPv6。如果是这样,那么我看不出有任何方法可以从 API 级别做到这一点。本地 PC 实际上可以安装 IPv4 协议,而无需连接到允许传输该协议上的流量的网络。即使 LAN 支持该协议,互联网连接本身也可能只支持 IPv6。
同样适用于其他方式(即支持本地 IPv6,但仅支持 Internet 上的 IPv4)。
在我看来,唯一可靠的方法与许多其他情况所需的方法相同:只需尝试一下,看看它是否有效。 IE。尝试通过所需的协议版本连接到 Internet 上的远程端点;如果失败,则不支持。如果成功,则支持。
编辑:
感谢您更新问题。它仍然不是最好的代码示例,但它稍微细化了问题。
我仍然不是 100% 你需要做的事情,也不是我是否有对你最有用的方法。但这里有一个简短的程序,我认为它可以满足您的需求:
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;
}
}
}
请注意,此代码示例不使用NetworkInformation.GetConnectionProfiles() 方法。尽管这似乎是扩展您当前方法的一种很有前途的方法,尽管 the documentation 实际上承诺 “调用 GetConnectionProfiles 方法会检索设备上当前建立的所有连接的配置文件,包括 Internet 连接。" [强调我的],事实证明并非如此。特别是,至少在我安装并启用了 Hyper-V 的机器上(对于那些进行 WinRT/Windows Phone 开发的人来说这是一个常见的场景:)),NetworkInformation.GetInternetConnectionProfile() 返回的 ConnectionProfile 对象实际上是 not 包含在NetworkInformation.GetConnectionProfiles() 返回的配置文件集合中。
因此,上面的代码示例所做的只是简单地识别与GetInternetConnectionProfile() 返回的ConnectionProfile 对应的任何主机名对象。
不幸的是,我所在的地方实际上并没有 IPv6 支持,所以我无法对此进行全面测试。 我能够在 IPv6 到 Internet 所在的不同网络上测试上述内容支持,我现在可以确认,至少在我的测试中,它按预期工作。该代码正确检测 IPv4 和 IPv6 协议上的 Internet 连接。我希望以上内容能满足您的需求。
顺便说一句,除了使用GetNetworkConnectivityLevel() 的明显问题(如您所述)没有提供实际使用的协议外,我发现该方法甚至没有返回至少直观地被认为是正确的信息。
特别是,调用FindConnectionProfilesAsync(new ConnectionProfileFilter { IsConnected = true }) 确实会返回与我用来连接互联网的连接(例如无线网络)对应的配置文件,但是当我在该配置文件上调用GetNetworkConnectivityLevel() 时,它只返回LocalAccess .我猜这与我上面提到的安装 Hyper-V 的问题有关。
这可以通过将GetConnectedProfileAsync() 方法返回的ConnectionProfile 与FindConnectionProfilesAsync() 返回的每个连接配置文件的NetworkAdapter 与GetInternetConnectionProfile() 返回的配置文件进行比较来解决。对顶级配置文件的网络适配器的配置文件进行间接处理似乎会产生预期的 Internet 连接配置文件。
当然,解决该问题并不能解决所使用协议的问题。我仅在其他人更多地针对配置文件管理方面而不是协议连接问题查看此答案时才提及它。